> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.solvimon.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.solvimon.com/_mcp/server.

# Credit types & wallets

Credit types define what a "credit" means in your system. Wallets hold a customer's credit balance. You need both before you can grant credits through a pricing plan.

---

## Credit types

A credit type is the unit of account for credits in your system. Before you can create a wallet or grant credits to a customer, you need at least one credit type defined.

Go to **Product Catalog** in the sidebar, then open **Credits & Wallets** and select the **Credits** tab. Click **Add credit type**.

![Credits & Wallets page, credit types tab](/_fern-img/de4f263eee0e31b4218ed7d205c1c193b0bd53d278a5d7013de3696ce98ee5b4.webp)

Fill in the following fields:

| Field                  | Required | Description                                                    |
| ---------------------- | -------- | -------------------------------------------------------------- |
| **Name**               | Yes      | Internal label for this credit type (e.g. "Streaming credits") |
| **Reference**          | Yes      | Unique identifier                                              |
| **Description**        | No       | Optional context for your team                                 |
| **Unit name singular** | No       | How a single credit appears in the UI (e.g. "Credit")          |
| **Unit name plural**   | No       | How multiple credits appear in the UI (e.g. "Credits")         |

![Add credit type form](/_fern-img/bf5f2f5ce18ed25eab871f11a0adb56a5981b02392fbaef4fa3137467afc4fe8.webp)

Click **Save and activate** to make the credit type available immediately, or **Save as draft** if you want to complete the configuration in a second moment.

---

## Wallets

A wallet holds a customer's balance for a given credit type. When credits are granted through a subscription, they are deposited into the matching wallet. When a customer consumes a usage-based product priced in credits, the balance is drawn down.

In **Credits & Wallets**, open the **Wallets** tab and click **Add wallet**.

![Wallets tab, list view](/_fern-img/0c63a693e6fd9cba12605f34048a8a7a6a0771159f69f3ca954886ea231f4e80.webp)

Fill in the following fields:

| Field           | Required | Description                                                             |
| --------------- | -------- | ----------------------------------------------------------------------- |
| **Wallet type** | Yes      | The type of wallet. Select **Credits** for credit-based wallets         |
| **Name**        | Yes      | Internal label for this wallet                                          |
| **Reference**   | Yes      | Unique identifier                                                       |
| **Grant type**  | Yes      | How the wallet is funded. Select **Credits** to fund with a credit type |
| **Credit type** | Yes      | The credit type this wallet holds                                       |

![Create wallet form](/_fern-img/3a5eea69209d9cbbfbc48b7335301cd3b8d8141be6606490501f07482b5dc8c3.webp)

> **Note**
>
> A wallet is a template-level definition. The actual per-customer balance is tracked when a customer subscribes to a pricing plan that grants credits into this wallet.

Once a wallet exists, see [Wallet top-ups](/platform-guides/wallets-credits/wallet-top-ups) for how credits get into it after the initial grant, including customer-driven purchases and automatic top-ups when the balance runs low.

### Wallet types

A wallet holds either credits or money, set by the wallet type:

| Wallet type | Funded with                                                          | Use it for                                                 |
| ----------- | -------------------------------------------------------------------- | ---------------------------------------------------------- |
| `CREDIT`    | A credit type, or a monetary amount converted into credits at a rate | Consumption priced in credits (API calls, minutes, tokens) |
| `BALANCE`   | A monetary amount in a currency                                      | Prepaid money that offsets invoiced charges                |

The wallet type is a template. Each customer who subscribes to a plan that grants into it gets their own wallet, and each grant into that wallet is tracked separately.

A `CREDIT` wallet type funded with an amount (`credit.amount_grant`) carries a `tax_category` and a `default_currency`. Both are the declared spending scope of the wallet type: money funded under one tax category must not become spendable under another. Once wallets exist for the wallet type, neither can be changed or removed; an attempt is rejected with a validation error on `credit.amount_grant.tax_category` or `credit.amount_grant.default_currency`. Changing either is still allowed on a wallet type that has no wallets yet.

### Request

POST [https://test.api.solvimon.com/v\{version}/wallets](https://test.api.solvimon.com/v\{version}/wallets)

**`Wallets_postWallets_example`**

```curl Wallets_postWallets_example
curl -X POST https://test.api.solvimon.com/v1/wallets \
     -H "X-API-KEY: <apiKey>" \
     -H "Content-Type: application/json" \
     -d '{
  "reference": "brightline_prepaid_credits",
  "wallet_type_id": "wtyp_BwDeeN0vxxHxWOCkua1f",
  "customer_id": "cust_lwDeeN0vxxHxMWCVef1S",
  "status": "ACTIVE"
}'
```

**`Wallets_postWallets_example`**

```python Wallets_postWallets_example
import requests

url = "https://test.api.solvimon.com/v1/wallets"

payload = {
    "reference": "brightline_prepaid_credits",
    "wallet_type_id": "wtyp_BwDeeN0vxxHxWOCkua1f",
    "customer_id": "cust_lwDeeN0vxxHxMWCVef1S",
    "status": "ACTIVE"
}
headers = {
    "X-API-KEY": "<apiKey>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`Wallets_postWallets_example`**

```javascript Wallets_postWallets_example
const url = 'https://test.api.solvimon.com/v1/wallets';
const options = {
  method: 'POST',
  headers: {'X-API-KEY': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"reference":"brightline_prepaid_credits","wallet_type_id":"wtyp_BwDeeN0vxxHxWOCkua1f","customer_id":"cust_lwDeeN0vxxHxMWCVef1S","status":"ACTIVE"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

**`Wallets_postWallets_example`**

```go Wallets_postWallets_example
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://test.api.solvimon.com/v1/wallets"

	payload := strings.NewReader("{\n  \"reference\": \"brightline_prepaid_credits\",\n  \"wallet_type_id\": \"wtyp_BwDeeN0vxxHxWOCkua1f\",\n  \"customer_id\": \"cust_lwDeeN0vxxHxMWCVef1S\",\n  \"status\": \"ACTIVE\"\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("X-API-KEY", "<apiKey>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`Wallets_postWallets_example`**

```ruby Wallets_postWallets_example
require 'uri'
require 'net/http'

url = URI("https://test.api.solvimon.com/v1/wallets")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["X-API-KEY"] = '<apiKey>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"reference\": \"brightline_prepaid_credits\",\n  \"wallet_type_id\": \"wtyp_BwDeeN0vxxHxWOCkua1f\",\n  \"customer_id\": \"cust_lwDeeN0vxxHxMWCVef1S\",\n  \"status\": \"ACTIVE\"\n}"

response = http.request(request)
puts response.read_body
```

**`Wallets_postWallets_example`**

```java Wallets_postWallets_example
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://test.api.solvimon.com/v1/wallets")
  .header("X-API-KEY", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{\n  \"reference\": \"brightline_prepaid_credits\",\n  \"wallet_type_id\": \"wtyp_BwDeeN0vxxHxWOCkua1f\",\n  \"customer_id\": \"cust_lwDeeN0vxxHxMWCVef1S\",\n  \"status\": \"ACTIVE\"\n}")
  .asString();
```

**`Wallets_postWallets_example`**

```php Wallets_postWallets_example
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://test.api.solvimon.com/v1/wallets', [
  'body' => '{
  "reference": "brightline_prepaid_credits",
  "wallet_type_id": "wtyp_BwDeeN0vxxHxWOCkua1f",
  "customer_id": "cust_lwDeeN0vxxHxMWCVef1S",
  "status": "ACTIVE"
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'X-API-KEY' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

**`Wallets_postWallets_example`**

```csharp Wallets_postWallets_example
using RestSharp;

var client = new RestClient("https://test.api.solvimon.com/v1/wallets");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "<apiKey>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"reference\": \"brightline_prepaid_credits\",\n  \"wallet_type_id\": \"wtyp_BwDeeN0vxxHxWOCkua1f\",\n  \"customer_id\": \"cust_lwDeeN0vxxHxMWCVef1S\",\n  \"status\": \"ACTIVE\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Wallets_postWallets_example`**

```swift Wallets_postWallets_example
import Foundation

let headers = [
  "X-API-KEY": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = [
  "reference": "brightline_prepaid_credits",
  "wallet_type_id": "wtyp_BwDeeN0vxxHxWOCkua1f",
  "customer_id": "cust_lwDeeN0vxxHxMWCVef1S",
  "status": "ACTIVE"
] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://test.api.solvimon.com/v1/wallets")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Response (201)

```json
{
  "object_type": "string",
  "id": "string",
  "reference": "string",
  "status": "DRAFT",
  "wallet_type_id": "string",
  "wallet_type": {
    "object_type": "string",
    "id": "string",
    "name": "string",
    "reference": "string",
    "status": "DRAFT",
    "type": "CREDIT",
    "credit": {
      "grant_type": "CREDITS",
      "amount_grant": {
        "default_currency": "AED",
        "tax_category": "STANDARD"
      },
      "credits_grant": {
        "credit_type_id": "string"
      }
    },
    "balance": {
      "default_currency": "string"
    },
    "created_at": "string",
    "updated_at": "string"
  },
  "auto_top_up_configs": [
    {
      "object_type": "string",
      "id": "string",
      "wallet_id": "string",
      "status": "ACTIVE",
      "threshold": {
        "amount": {
          "quantity": "string",
          "currency": "AED"
        },
        "credits": {
          "quantity": "string",
          "credit_type_id": "string",
          "credit_type": {
            "object_type": "string",
            "id": "string",
            "reference": "string",
            "status": "DRAFT",
            "name": "string",
            "description": "string",
            "unit_name": {
              "singular": "string",
              "plural": "string"
            },
            "created_at": "string",
            "updated_at": "string"
          }
        }
      },
      "topup_amount": {
        "quantity": "string",
        "currency": "AED"
      },
      "pricing_plan_schedule_id": "string",
      "pricing_item_id": "string",
      "payment_method_id": "string",
      "created_at": "string",
      "updated_at": "string"
    }
  ],
  "customer_id": "string",
  "created_at": "string",
  "updated_at": "string"
}
```

Wallets follow the standard resource lifecycle. A newly created wallet is in `DRAFT` until you activate it with `POST /v{version}/wallets/{resourceIdOrReference}/activate`, and can later be deactivated, deprecated, or archived.

### An amount-denominated wallet pays for the invoice

A `CREDIT` wallet type funded with an amount holds money rather than credits, so it does not reduce a volume the way credits do. It reduces the charge. A funded wallet pays for the invoice lines it is allowed to pay for, and the customer is invoiced for the rest.

The wallet holds a net amount. Tax was already charged on the top-up that funded it: a top-up of 12.10 EUR including 21% VAT puts 10.00 EUR in the wallet. So the money comes off the net side of the line, and the covered part is not taxed a second time:

|                         | Net    | VAT  | Total  |
| ----------------------- | ------ | ---- | ------ |
| Line as priced          | 30.00  | 6.30 | 36.30  |
| Covered from the wallet | -10.00 | 0.00 | -10.00 |
| Charged                 | 20.00  | 4.20 | 24.20  |

Coverage is always split, never skipped. A balance that does not cover the whole line covers part of it, and the remainder is charged and taxed as normal. A wallet with nothing in it produces no wallet block on the line at all.

**Which lines it may pay for.** Only lines whose product tax category matches the wallet type's `credit.amount_grant.tax_category`. That is what the tax category on the wallet type declares: money funded under one tax category must not become spendable under another. Lines outside it are untouched.

**When it is applied.** Last. The deduction runs after included volume, after credits, after discounts and after minimum commitment, on the net amount those leave behind, and therefore before tax is calculated.

The order matters in both directions. The wallet is the only reduction denominated in money, so anything applied after it would change the figure the wallet was measured against. And anything applied after tax would leave the deduction taxed.

A customer holding both kinds of wallet spends credits first. Credits reduce the volume being priced; the money wallet reduces what that pricing came to.

**What each wallet paid.** The charge reports one entry per wallet that paid, in `wallet_balances`:

**`One wallet's share of a charge`**

```json One wallet's share of a charge
"wallet_balances": [
  {
    "wallet_id": "wall_5RmXe2QbtKfYuA9DcNH3P",
    "used_balance": { "amount": { "quantity": "10.00", "currency": "EUR" } },
    "left_balance": { "amount": { "quantity": "0.00", "currency": "EUR" } },
    "available_balance": { "amount": { "quantity": "10.00", "currency": "EUR" } }
  }
]
```

`used_balance` is what the charge took out, `available_balance` is what it could have drawn on, and `left_balance` is what remains of that for further usage in the same period. A wallet holding credits reports the same three fields with a `credits` value instead of an `amount`.

> **Warning**
>
> `wallet_balance_details`, with `used_wallet_credits`, `left_wallet_credits` and `available_wallet_credits`, is deprecated in favour of `wallet_balances`. It holds one wallet at a time, so a charge paid by a credits wallet and a money wallet reports the figures of whichever paid last, and it can only express credits. It keeps working for backwards compatibility.

**Granting into the wallet.** A grant has to be in the wallet's own currency, since there is no conversion between one currency and another on the way in. A fixed grant in another currency is rejected with `wallet type <reference> is denominated in EUR, but the grant is in USD`. A grant that takes a percentage of pricing in another currency is rejected for the same reason, and the error names the two ways out: grant a fixed amount in the wallet's currency, or grant into a wallet type denominated in the pricing currency.

A wallet type created before `default_currency` became mandatory has none. Nothing can be granted into it until it is given one.

### Spend on an amount-denominated wallet books out at final

A `CREDIT` wallet type funded with an amount keeps its ledger in a currency. Usage covered by such a wallet is held as a reservation while the invoice is not yet final: the available balance already reflects the reservation, so a second invoice cannot spend the same money, but the money has not yet left the wallet.

When the invoice goes `FINAL`, the covered amount leaves the wallet, oldest-expiring grant first. Solvimon recognises it as revenue with no tax, because tax was already charged on the top-up that funded the balance.

> **Note**
>
> Voiding or recalculating the invoice before it is final releases the reservation, and the balance becomes spendable again. Re-running a final invoice does not book the spend twice.

### Read a wallet with its type and top-up rules

`GET /v1/wallets` and `GET /v1/wallets/{id}` accept `expand[]`, which saves resolving a wallet's denomination and its funding rules through separate calls:

| Expansion             | Inlines                                                                                                 |
| --------------------- | ------------------------------------------------------------------------------------------------------- |
| `wallet_type_id`      | The full `wallet_type`, so you have the denomination without a second lookup                            |
| `auto_top_up_configs` | The [automatic top-up](/platform-guides/wallets-credits/wallet-top-ups) configs attached to that wallet |

### Request

GET [https://test.api.solvimon.com/v\{version}/wallets/\{resourceIdOrReference}](https://test.api.solvimon.com/v\{version}/wallets/\{resourceIdOrReference})

```curl
curl -G https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v \
     -H "X-API-KEY: <apiKey>" \
     -d "expand[]=wallet_type_id" \
     -d "expand[]=auto_top_up_configs"
```

```python
import requests

url = "https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v"

querystring = {"expand[]":"[\"wallet_type_id\",\"auto_top_up_configs\"]"}

headers = {"X-API-KEY": "<apiKey>"}

response = requests.get(url, headers=headers, params=querystring)

print(response.json())
```

```javascript
const url = 'https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v?expand%5B%5D=%5B%22wallet_type_id%22%2C%22auto_top_up_configs%22%5D';
const options = {method: 'GET', headers: {'X-API-KEY': '<apiKey>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v?expand%5B%5D=%5B%22wallet_type_id%22%2C%22auto_top_up_configs%22%5D"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("X-API-KEY", "<apiKey>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v?expand%5B%5D=%5B%22wallet_type_id%22%2C%22auto_top_up_configs%22%5D")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["X-API-KEY"] = '<apiKey>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v?expand%5B%5D=%5B%22wallet_type_id%22%2C%22auto_top_up_configs%22%5D")
  .header("X-API-KEY", "<apiKey>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v?expand%5B%5D=%5B%22wallet_type_id%22%2C%22auto_top_up_configs%22%5D', [
  'headers' => [
    'X-API-KEY' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v?expand%5B%5D=%5B%22wallet_type_id%22%2C%22auto_top_up_configs%22%5D");
var request = new RestRequest(Method.GET);
request.AddHeader("X-API-KEY", "<apiKey>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["X-API-KEY": "<apiKey>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v?expand%5B%5D=%5B%22wallet_type_id%22%2C%22auto_top_up_configs%22%5D")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Response (200)

```json
{
  "object_type": "WALLET",
  "id": "wall_TwDeeN0tYSY3F7BkeN1v",
  "wallet_type_id": "wtyp_qwDeeN0tYSY3F7BkeN1w",
  "wallet_type": {
    "object_type": "WALLET_TYPE",
    "id": "wtyp_qwDeeN0tYSY3F7BkeN1w",
    "name": "Support credits"
  },
  "auto_top_up_configs": [
    {
      "object_type": "AUTO_TOP_UP_CONFIG",
      "id": "atuc_ewDeeN0tYSY3F7BkeN1x",
      "threshold": {
        "credits": {
          "quantity": "500",
          "credit_type_id": "crty_hwDeeN0vcYJaBLAc0C1W"
        }
      }
    }
  ]
}
```

The same expansions apply when a wallet is reached through the customer balance call, using the nested key:

### Request

POST [https://test.api.solvimon.com/v\{version}/customers/\{resourceIdOrReference}/wallets/balance](https://test.api.solvimon.com/v\{version}/customers/\{resourceIdOrReference}/wallets/balance)

```curl
curl -X POST "https://test.api.solvimon.com/v1/customers/cust_AbD3DqausjOYiMNDZY11F/wallets/balance?expand[]=wallet_balances.wallet_id&expand[]=wallet_balances.wallet.wallet_type_id" \
     -H "X-API-KEY: <apiKey>" \
     -H "Content-Type: application/json" \
     -d '{}'
```

```python
import requests

url = "https://test.api.solvimon.com/v1/customers/cust_AbD3DqausjOYiMNDZY11F/wallets/balance"

querystring = {"expand[]":"[\"wallet_balances.wallet_id\",\"wallet_balances.wallet.wallet_type_id\"]"}

payload = {}
headers = {
    "X-API-KEY": "<apiKey>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers, params=querystring)

print(response.json())
```

```javascript
const url = 'https://test.api.solvimon.com/v1/customers/cust_AbD3DqausjOYiMNDZY11F/wallets/balance?expand%5B%5D=%5B%22wallet_balances.wallet_id%22%2C%22wallet_balances.wallet.wallet_type_id%22%5D';
const options = {
  method: 'POST',
  headers: {'X-API-KEY': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://test.api.solvimon.com/v1/customers/cust_AbD3DqausjOYiMNDZY11F/wallets/balance?expand%5B%5D=%5B%22wallet_balances.wallet_id%22%2C%22wallet_balances.wallet.wallet_type_id%22%5D"

	payload := strings.NewReader("{}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("X-API-KEY", "<apiKey>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://test.api.solvimon.com/v1/customers/cust_AbD3DqausjOYiMNDZY11F/wallets/balance?expand%5B%5D=%5B%22wallet_balances.wallet_id%22%2C%22wallet_balances.wallet.wallet_type_id%22%5D")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["X-API-KEY"] = '<apiKey>'
request["Content-Type"] = 'application/json'
request.body = "{}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://test.api.solvimon.com/v1/customers/cust_AbD3DqausjOYiMNDZY11F/wallets/balance?expand%5B%5D=%5B%22wallet_balances.wallet_id%22%2C%22wallet_balances.wallet.wallet_type_id%22%5D")
  .header("X-API-KEY", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://test.api.solvimon.com/v1/customers/cust_AbD3DqausjOYiMNDZY11F/wallets/balance?expand%5B%5D=%5B%22wallet_balances.wallet_id%22%2C%22wallet_balances.wallet.wallet_type_id%22%5D', [
  'body' => '{}',
  'headers' => [
    'Content-Type' => 'application/json',
    'X-API-KEY' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://test.api.solvimon.com/v1/customers/cust_AbD3DqausjOYiMNDZY11F/wallets/balance?expand%5B%5D=%5B%22wallet_balances.wallet_id%22%2C%22wallet_balances.wallet.wallet_type_id%22%5D");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "<apiKey>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "X-API-KEY": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = [] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://test.api.solvimon.com/v1/customers/cust_AbD3DqausjOYiMNDZY11F/wallets/balance?expand%5B%5D=%5B%22wallet_balances.wallet_id%22%2C%22wallet_balances.wallet.wallet_type_id%22%5D")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Response (200)

```json
{
  "wallet_balances": [
    {
      "wallet_id": "wall_TwDeeN0tYSY3F7BkeN1v",
      "wallet": {
        "object_type": "WALLET",
        "id": "wall_TwDeeN0tYSY3F7BkeN1v",
        "wallet_type_id": "wtyp_qwDeeN0tYSY3F7BkeN1w",
        "wallet_type": {
          "object_type": "WALLET_TYPE",
          "id": "wtyp_qwDeeN0tYSY3F7BkeN1w",
          "name": "Support credits"
        }
      },
      "wallet_balance": {
        "balance": {
          "credits": {
            "quantity": "6000",
            "credit_type_id": "crty_hwDeeN0vcYJaBLAc0C1W"
          }
        }
      }
    }
  ]
}
```

Rendering a wallet with its denomination and its top-up rules took three calls before these expansions. See [Expanding responses](/platform-guides/for-developers/expanding-responses) for how `expand[]` behaves generally.

### See whose usage reserved the balance

A wallet balance shared by several child customers, or spent through several subscriptions, reports one reserved figure with no way to see where it came from. Pass `include_customer_details` on a balance call to get the reserved balance split per customer:

### Request

POST [https://test.api.solvimon.com/v\{version}/wallets/\{resourceIdOrReference}/balance](https://test.api.solvimon.com/v\{version}/wallets/\{resourceIdOrReference}/balance)

**`Wallet balance with the reserved balance split per customer`**

```curl Wallet balance with the reserved balance split per customer
curl -X POST https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v/balance \
     -H "X-API-KEY: <apiKey>" \
     -H "Content-Type: application/json" \
     -d '{
  "include_customer_details": true
}'
```

**`Wallet balance with the reserved balance split per customer`**

```python Wallet balance with the reserved balance split per customer
import requests

url = "https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v/balance"

payload = { "include_customer_details": True }
headers = {
    "X-API-KEY": "<apiKey>",
    "Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.json())
```

**`Wallet balance with the reserved balance split per customer`**

```javascript Wallet balance with the reserved balance split per customer
const url = 'https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v/balance';
const options = {
  method: 'POST',
  headers: {'X-API-KEY': '<apiKey>', 'Content-Type': 'application/json'},
  body: '{"include_customer_details":true}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

**`Wallet balance with the reserved balance split per customer`**

```go Wallet balance with the reserved balance split per customer
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v/balance"

	payload := strings.NewReader("{\n  \"include_customer_details\": true\n}")

	req, _ := http.NewRequest("POST", url, payload)

	req.Header.Add("X-API-KEY", "<apiKey>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

**`Wallet balance with the reserved balance split per customer`**

```ruby Wallet balance with the reserved balance split per customer
require 'uri'
require 'net/http'

url = URI("https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v/balance")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["X-API-KEY"] = '<apiKey>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"include_customer_details\": true\n}"

response = http.request(request)
puts response.read_body
```

**`Wallet balance with the reserved balance split per customer`**

```java Wallet balance with the reserved balance split per customer
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v/balance")
  .header("X-API-KEY", "<apiKey>")
  .header("Content-Type", "application/json")
  .body("{\n  \"include_customer_details\": true\n}")
  .asString();
```

**`Wallet balance with the reserved balance split per customer`**

```php Wallet balance with the reserved balance split per customer
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v/balance', [
  'body' => '{
  "include_customer_details": true
}',
  'headers' => [
    'Content-Type' => 'application/json',
    'X-API-KEY' => '<apiKey>',
  ],
]);

echo $response->getBody();
```

**`Wallet balance with the reserved balance split per customer`**

```csharp Wallet balance with the reserved balance split per customer
using RestSharp;

var client = new RestClient("https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v/balance");
var request = new RestRequest(Method.POST);
request.AddHeader("X-API-KEY", "<apiKey>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"include_customer_details\": true\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

**`Wallet balance with the reserved balance split per customer`**

```swift Wallet balance with the reserved balance split per customer
import Foundation

let headers = [
  "X-API-KEY": "<apiKey>",
  "Content-Type": "application/json"
]
let parameters = ["include_customer_details": true] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://test.api.solvimon.com/v1/wallets/wall_TwDeeN0tYSY3F7BkeN1v/balance")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Response (200)

```json
{
  "balance": {
    "credits": {
      "quantity": "6000",
      "credit_type_id": "crty_hwDeeN0vcYJaBLAc0C1W"
    }
  },
  "reserved_balance": {
    "credits": {
      "quantity": "1750",
      "credit_type_id": "crty_hwDeeN0vcYJaBLAc0C1W"
    }
  },
  "open_balance": {
    "credits": {
      "quantity": "4250",
      "credit_type_id": "crty_hwDeeN0vcYJaBLAc0C1W"
    }
  },
  "balance_at": "2026-09-07T10:00:00Z",
  "customer_details": [
    {
      "customer_id": "cust_MwDR9l0vsgwcV6CRqw14",
      "reserved_balance": {
        "credits": {
          "quantity": "1200",
          "credit_type_id": "crty_hwDeeN0vcYJaBLAc0C1W"
        }
      }
    },
    {
      "customer_id": "cust_qwDRHT0vsJoJuFCkPm1A",
      "reserved_balance": {
        "credits": {
          "quantity": "550",
          "credit_type_id": "crty_hwDeeN0vcYJaBLAc0C1W"
        }
      }
    }
  ]
}
```

Each entry in the returned `customer_details` carries `customer_id` and that customer's share of the reserved balance. The split is recorded when an invoice is built or refreshed, so it reflects usage that has actually been drafted against the wallet, not a live estimate. It only covers credit wallets: a `BALANCE` wallet returns an empty `customer_details`, since the attribution is recorded per credit type on the invoice line. The same flag works on `POST /v1/customers/{id}/wallets/balance`. It defaults to `false`, so existing integrations are unaffected. See [Seat-based credits](/platform-guides/wallets-credits/seat-based-credits#see-whose-usage-reserved-the-balance) for a worked example on a seat-scaled pool.

---

## Credit pools and commitments

Two things are commonly mistaken for credit pools. Neither is one:

* **A wallet is not shared across customers.** Every wallet balance belongs to a single customer. A parent company and its children each hold their own wallets; there is no cross-customer pool that several customers draw from, and there is no pooling across a customer's own wallets. Consumption priced in a given credit type draws only from the wallet holding that credit type.
* **A minimum-spend commitment is not a credit balance.** A commitment sets a floor on what a customer is invoiced over a period. If actual charges fall short, the shortfall is invoiced as a true-up. Nothing is prepaid, nothing is granted into a wallet, and nothing expires. See [Schedule configurations](/platform-guides/customers-and-billing/subscriptions/schedule-configurations).

Use a wallet when the customer pays up front and draws down. Use a commitment when the customer promises a spend level and you bill against it. The two can coexist on one subscription: a committed annual spend that is delivered as monthly credit grants.

---