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

Fill in the following fields:

FieldRequiredDescription
NameYesInternal label for this credit type (e.g. “Streaming credits”)
ReferenceYesUnique identifier
DescriptionNoOptional context for your team
Unit name singularNoHow a single credit appears in the UI (e.g. “Credit”)
Unit name pluralNoHow multiple credits appear in the UI (e.g. “Credits”)

Add credit type form

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

Fill in the following fields:

FieldRequiredDescription
Wallet typeYesThe type of wallet. Select Credits for credit-based wallets
NameYesInternal label for this wallet
ReferenceYesUnique identifier
Grant typeYesHow the wallet is funded. Select Credits to fund with a credit type
Credit typeYesThe credit type this wallet holds

Create wallet form

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 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 typeFunded withUse it for
CREDITA credit type, or a monetary amount converted into credits at a rateConsumption priced in credits (API calls, minutes, tokens)
BALANCEA monetary amount in a currencyPrepaid 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.

POST
/v:version/wallets
curl -X POST https://test.api.solvimon.com/v1/wallets \
-H "X-API-KEY: <apiKey>" \
-H "Content-Type: application/json" \
-d '{
"reference": "string",
"wallet_type_id": "string",
"customer_id": "string"
}'
Response
{
"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.

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.

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:

ExpansionInlines
wallet_type_idThe full wallet_type, so you have the denomination without a second lookup
auto_top_up_configsThe automatic top-up configs attached to that wallet
GET
/v:version/wallets/:resourceIdOrReference
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"
Response
{
"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:

POST
/v:version/customers/:resourceIdOrReference/wallets/balance
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 '{}'
Response
{
"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 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:

POST
/v:version/wallets/:resourceIdOrReference/balance
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
}'
Response
{
"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 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.

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.