Skip to content

Wallets tools

MCP tools for Wallets: wallets_create, wallets_get, wallets_list, wallets_transactions_list, wallets_update.

  • wallets_create: Open a customer's wallet
  • wallets_get: Get a wallet and its balance
  • wallets_list: List wallets
  • wallets_transactions_list: List a wallet's transactions
  • wallets_update: Update a wallet's settings or status

wallets_create

Open a customer's wallet. Operation wallets.create · Brand level · permission wallets:write · risk tier write · since M6

Returns the customer's wallet in a currency, opening it when it doesn't exist yet: a customer has one wallet per currency in each brand and mode (spec §17.1). Top-ups, credit packs and subscription credits open the wallet themselves; open it here to grant credits (credit_grants.create) before the customer has bought any.

Calling it again returns the same wallet, whatever its status.

Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: true · openWorldHint: false

Arguments

ArgumentTypeRequiredDescription
customerIdID (cus_…)yesThe customer (cus_…) of the brand.
currencystringyesThe wallet's currency (one wallet per customer and currency).
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe brand to act on (brd_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand.
idempotency_keystringnoA unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters)
dry_runbooleannotrue: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false)
  • Brand: pass brand_id with an organization or entity key; a brand key acts on its own brand.
  • Idempotency: the result returns the idempotency_key used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
  • Dry run: supported. dry_run: true checks permissions and rules and computes the result, then rolls everything back.
  • Plan feature: needs usage_billing.enabled.

Errors

Example

Open a customer's EUR wallet

Arguments:

JSON
{
  "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0aa",
  "currency": "EUR",
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "id": "wal_01m4ty7w2a5qx7mhd9k8w6s0b1",
  "object": "wallet",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "livemode": false,
  "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0aa",
  "currency": "EUR",
  "status": "active",
  "statusReason": null,
  "statusChangedAt": null,
  "available": {
    "amount": "0",
    "currency": "EUR"
  },
  "promo": {
    "amount": "0",
    "currency": "EUR"
  },
  "reserved": {
    "amount": "0",
    "currency": "EUR"
  },
  "balance": {
    "amount": "0",
    "currency": "EUR"
  },
  "lowBalanceThreshold": null,
  "lowBalance": false,
  "autoReload": null,
  "createdAt": "2026-10-14T09:00:00.000Z",
  "updatedAt": "2026-10-16T10:15:00.000Z",
  "upcomingExpiries": []
}

wallets_get

Get a wallet. Operation wallets.get · Brand level · permission wallets:read · risk tier read · since M6

Returns a wallet with its balances, its settings and the next credits to expire (spec §17.1):

  • available: spendable purchased, subscription and adjustment credits; promo: spendable promo credits (spent first); reserved: held by open reservations and leases; balance: all three together;
  • upcomingExpiries: the next grants to expire, soonest first, with what is left of each;
  • lowBalanceThreshold and lowBalance, the auto-reload settings (autoReload) and the status.

Amounts are integer micros in the wallet's currency.

Annotations: readOnlyHint: true · destructiveHint: false · idempotentHint: true · openWorldHint: false

Arguments

ArgumentTypeRequiredDescription
idID (wal_…)yesThe wallet (wal_…).
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe brand to act on (brd_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand.
  • Brand: pass brand_id with an organization or entity key; a brand key acts on its own brand.
  • Read-only: changes nothing; idempotency_key is ignored.

Errors

Examples

A wallet with promo credits expiring next month

Arguments:

JSON
{
  "id": "wal_01m4ty7w2a5qx7mhd9k8w6s0b1",
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz"
}

Result output:

JSON
{
  "id": "wal_01m4ty7w2a5qx7mhd9k8w6s0b1",
  "object": "wallet",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "livemode": false,
  "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0aa",
  "currency": "EUR",
  "status": "active",
  "statusReason": null,
  "statusChangedAt": null,
  "available": {
    "amount": "77000000",
    "currency": "EUR"
  },
  "promo": {
    "amount": "5000000",
    "currency": "EUR"
  },
  "reserved": {
    "amount": "3000000",
    "currency": "EUR"
  },
  "balance": {
    "amount": "85000000",
    "currency": "EUR"
  },
  "lowBalanceThreshold": {
    "amount": "10000000",
    "currency": "EUR"
  },
  "lowBalance": false,
  "autoReload": null,
  "createdAt": "2026-10-14T09:00:00.000Z",
  "updatedAt": "2026-10-16T10:15:00.000Z",
  "upcomingExpiries": [
    {
      "grantId": "grant_01m4ty7w2a5qx7mhd9k8w6s0b3",
      "source": "promo",
      "remaining": {
        "amount": "5000000",
        "currency": "EUR"
      },
      "expiresAt": "2026-11-01T00:00:00.000Z"
    }
  ]
}

A wallet with auto-reload

Arguments:

JSON
{
  "id": "wal_01m4ty7w2a5qx7mhd9k8w6s0b1",
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz"
}

Result output:

JSON
{
  "id": "wal_01m4ty7w2a5qx7mhd9k8w6s0b1",
  "object": "wallet",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "livemode": false,
  "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0aa",
  "currency": "EUR",
  "status": "active",
  "statusReason": null,
  "statusChangedAt": null,
  "available": {
    "amount": "77000000",
    "currency": "EUR"
  },
  "promo": {
    "amount": "5000000",
    "currency": "EUR"
  },
  "reserved": {
    "amount": "3000000",
    "currency": "EUR"
  },
  "balance": {
    "amount": "85000000",
    "currency": "EUR"
  },
  "lowBalanceThreshold": {
    "amount": "10000000",
    "currency": "EUR"
  },
  "lowBalance": false,
  "autoReload": {
    "enabled": true,
    "below": {
      "amount": "10000000",
      "currency": "EUR"
    },
    "amount": {
      "amount": "50000000",
      "currency": "EUR"
    },
    "paymentMethodId": "pm_01m4ty7w2a5qx7mhd9k8w6s0b6",
    "failureCount": 0,
    "pendingSince": null,
    "lastFailureAt": null,
    "disabledAt": null
  },
  "createdAt": "2026-10-14T09:00:00.000Z",
  "updatedAt": "2026-10-16T10:15:00.000Z",
  "upcomingExpiries": [
    {
      "grantId": "grant_01m4ty7w2a5qx7mhd9k8w6s0b3",
      "source": "promo",
      "remaining": {
        "amount": "5000000",
        "currency": "EUR"
      },
      "expiresAt": "2026-11-01T00:00:00.000Z"
    }
  ]
}

wallets_list

List wallets. Operation wallets.list · Brand level · permission wallets:read · risk tier read · since M6

Lists the brand's wallets in the mode of the request, newest first, with their balances (without the upcoming expiries: get a wallet for those).

  • customerId: one customer's wallets (one per currency);
  • currency, status: only wallets in this currency or with this status.

Paginate with limit (1–100, default 10) and starting_after (the next_cursor of the previous page).

Annotations: readOnlyHint: true · destructiveHint: false · idempotentHint: true · openWorldHint: false

Arguments

ArgumentTypeRequiredDescription
limitintegerno(1–100)
starting_afterID (wal_…)no–
customerIdID (cus_…)noOnly this customer's wallets (spec: ?customer=).
currencystringnoOnly wallets in this currency.
statusone of active, frozen, closednoOnly wallets with this status.
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe brand to act on (brd_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand.
  • Brand: pass brand_id with an organization or entity key; a brand key acts on its own brand.
  • Read-only: changes nothing; idempotency_key is ignored.

Errors

Example

A customer's wallets

Arguments:

JSON
{
  "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0aa",
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz"
}

Result output:

JSON
{
  "object": "list",
  "data": [
    {
      "id": "wal_01m4ty7w2a5qx7mhd9k8w6s0b1",
      "object": "wallet",
      "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
      "livemode": false,
      "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0aa",
      "currency": "EUR",
      "status": "active",
      "statusReason": null,
      "statusChangedAt": null,
      "available": {
        "amount": "77000000",
        "currency": "EUR"
      },
      "promo": {
        "amount": "5000000",
        "currency": "EUR"
      },
      "reserved": {
        "amount": "3000000",
        "currency": "EUR"
      },
      "balance": {
        "amount": "85000000",
        "currency": "EUR"
      },
      "lowBalanceThreshold": {
        "amount": "10000000",
        "currency": "EUR"
      },
      "lowBalance": false,
      "autoReload": null,
      "createdAt": "2026-10-14T09:00:00.000Z",
      "updatedAt": "2026-10-16T10:15:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

wallets_transactions_list

List a wallet's transactions. Operation wallets.transactions.list · Brand level · permission wallets:read · risk tier read · since M6

Lists the ledger transactions that moved the wallet, newest first: top-ups, grants, reservations, captures, releases and expiries. Each shows the signed change of available, promo and reserved and of the balance (reserving and releasing move credits inside the wallet, so they don't change the balance), with the reservation, grant or payment it belongs to.

Paginate with limit (1–100, default 10) and starting_after (a txn_… ID).

Annotations: readOnlyHint: true · destructiveHint: false · idempotentHint: true · openWorldHint: false

Arguments

ArgumentTypeRequiredDescription
idID (wal_…)yesThe wallet (wal_…).
limitintegerno(1–100)
starting_afterID (txn_…)no–
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe brand to act on (brd_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand.
  • Brand: pass brand_id with an organization or entity key; a brand key acts on its own brand.
  • Read-only: changes nothing; idempotency_key is ignored.

Errors

Example

A top-up, then a capture

Arguments:

JSON
{
  "id": "wal_01m4ty7w2a5qx7mhd9k8w6s0b1",
  "limit": 2,
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz"
}

Result output:

JSON
{
  "object": "list",
  "data": [
    {
      "id": "txn_01m4ty7w2a5qx7mhd9k8w6s0b8",
      "object": "wallet_transaction",
      "walletId": "wal_01m4ty7w2a5qx7mhd9k8w6s0b1",
      "kind": "capture",
      "status": "posted",
      "memo": "Usage capture",
      "available": {
        "amount": "0",
        "currency": "EUR"
      },
      "promo": {
        "amount": "0",
        "currency": "EUR"
      },
      "reserved": {
        "amount": "-1250000",
        "currency": "EUR"
      },
      "balance": {
        "amount": "-1250000",
        "currency": "EUR"
      },
      "reservationId": "res_01m4ty7w2a5qx7mhd9k8w6s0b4",
      "grantId": null,
      "paymentId": null,
      "effectiveAt": "2026-10-16T10:16:00.000Z",
      "createdAt": "2026-10-16T10:16:00.000Z"
    },
    {
      "id": "txn_01m4ty7w2a5qx7mhd9k8w6s0b7",
      "object": "wallet_transaction",
      "walletId": "wal_01m4ty7w2a5qx7mhd9k8w6s0b1",
      "kind": "topup",
      "status": "posted",
      "memo": "Credit top-up",
      "available": {
        "amount": "80000000",
        "currency": "EUR"
      },
      "promo": {
        "amount": "0",
        "currency": "EUR"
      },
      "reserved": {
        "amount": "0",
        "currency": "EUR"
      },
      "balance": {
        "amount": "80000000",
        "currency": "EUR"
      },
      "reservationId": null,
      "grantId": "grant_01m4ty7w2a5qx7mhd9k8w6s0b2",
      "paymentId": "pay_01m4ty7w2a5qx7mhd9k8w6s0b5",
      "effectiveAt": "2026-10-14T09:00:00.000Z",
      "createdAt": "2026-10-14T09:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}

wallets_update

Update a wallet. Operation wallets.update · Brand level · permission wallets:write · risk tier write · since M6

Changes a wallet's low-balance threshold, its auto-reload settings or its status. Send only what changes; null removes the threshold or the auto-reload settings.

  • lowBalanceThreshold: wallet.low_balance is sent when spending or expiry takes the balance below it, once per dip (again only after the balance is back at or above it). wallet.depleted is sent when it reaches zero.
  • autoReload (spec §14.3): when the balance falls below below, the customer's saved payment method (paymentMethodId) is charged amount off-session and the wallet is credited. Enabling it resets the failure count; it turns off by itself after 2 failed reloads.
  • status: frozen stops new reservations and leases at once (reservations made before still settle); closed retires an empty wallet (no credits, no open reservations); active unfreezes or reopens it. Freezing and closing need a reason. Freezing emits wallet.frozen.

Annotations: readOnlyHint: false · destructiveHint: false · idempotentHint: true · openWorldHint: false

Arguments

ArgumentTypeRequiredDescription
idID (wal_…)yesThe wallet (wal_…).
lowBalanceThresholdobject or nullnoSend wallet.low_balance when the balance falls below this; null removes it.
autoReloadobject or nullnoAuto-reload settings; null removes them.
statusone of active, frozen, closednofrozen stops spending (no new reservations or leases), closed retires an empty wallet, active unfreezes or reopens it.
reasonstringnoWhy the wallet is frozen or closed: required with status: frozen or closed. (1–500 characters)
entity_idID (ent_…)noOptional: the brand's legal entity (ent_…); brand_id alone is enough.
brand_idID (brd_…)noThe brand to act on (brd_…), inside your API key's reach. Needed with an organization or entity key; a brand key acts on its own brand.
idempotency_keystringnoA unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's idempotency_key. (1–255 characters)
dry_runbooleannotrue: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default false)
  • Brand: pass brand_id with an organization or entity key; a brand key acts on its own brand.
  • Idempotency: the result returns the idempotency_key used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
  • Dry run: supported. dry_run: true checks permissions and rules and computes the result, then rolls everything back.

Errors

  • validation_failed: Nothing to change, an amount isn't positive (or a reload amount isn't whole minor units), or reason is missing when freezing or closing.
  • resource_not_found: This brand has no such wallet in this mode (wallets belong to one brand and one mode).
  • wallet_currency_mismatch: A threshold or reload amount isn't in the wallet's currency.
  • wallet_payment_method_invalid: Auto-reload is enabled with a payment method that isn't the customer's, or was detached.
  • wallet_not_empty: The wallet is closed while it still has credits or open reservations (details.balance, details.open_reservations).
  • wallet_closed: A closed wallet is frozen: reopen it first (status: active).
  • version_conflict: The wallet changed at the same moment (another reservation, capture or grant); retry.
  • scope_required: The request names no brand (an org or entity key without Ownrecord-Brand).
  • permission_denied: You can't change this brand's wallets (wallets:write: owners, admins and support).
  • livemode_not_allowed: You have no live-mode access, so you can't use live wallets.

Examples

Warn below €10 and reload €50 below €10

Arguments:

JSON
{
  "id": "wal_01m4ty7w2a5qx7mhd9k8w6s0b1",
  "lowBalanceThreshold": {
    "amount": "10000000",
    "currency": "EUR"
  },
  "autoReload": {
    "enabled": true,
    "below": {
      "amount": "10000000",
      "currency": "EUR"
    },
    "amount": {
      "amount": "50000000",
      "currency": "EUR"
    },
    "paymentMethodId": "pm_01m4ty7w2a5qx7mhd9k8w6s0b6"
  },
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "id": "wal_01m4ty7w2a5qx7mhd9k8w6s0b1",
  "object": "wallet",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "livemode": false,
  "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0aa",
  "currency": "EUR",
  "status": "active",
  "statusReason": null,
  "statusChangedAt": null,
  "available": {
    "amount": "77000000",
    "currency": "EUR"
  },
  "promo": {
    "amount": "5000000",
    "currency": "EUR"
  },
  "reserved": {
    "amount": "3000000",
    "currency": "EUR"
  },
  "balance": {
    "amount": "85000000",
    "currency": "EUR"
  },
  "lowBalanceThreshold": {
    "amount": "10000000",
    "currency": "EUR"
  },
  "lowBalance": false,
  "autoReload": {
    "enabled": true,
    "below": {
      "amount": "10000000",
      "currency": "EUR"
    },
    "amount": {
      "amount": "50000000",
      "currency": "EUR"
    },
    "paymentMethodId": "pm_01m4ty7w2a5qx7mhd9k8w6s0b6",
    "failureCount": 0,
    "pendingSince": null,
    "lastFailureAt": null,
    "disabledAt": null
  },
  "createdAt": "2026-10-14T09:00:00.000Z",
  "updatedAt": "2026-10-16T10:15:00.000Z",
  "upcomingExpiries": [
    {
      "grantId": "grant_01m4ty7w2a5qx7mhd9k8w6s0b3",
      "source": "promo",
      "remaining": {
        "amount": "5000000",
        "currency": "EUR"
      },
      "expiresAt": "2026-11-01T00:00:00.000Z"
    }
  ]
}

Freeze a wallet during a dispute

Arguments:

JSON
{
  "id": "wal_01m4ty7w2a5qx7mhd9k8w6s0b1",
  "status": "frozen",
  "reason": "Chargeback opened on the last top-up",
  "brand_id": "brd_01jbx4m3v8e9t0s6k2c5n7q1wz",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}

Result output:

JSON
{
  "id": "wal_01m4ty7w2a5qx7mhd9k8w6s0b1",
  "object": "wallet",
  "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
  "livemode": false,
  "customerId": "cus_01m4ty3c2b5qx7mhd9k8w6s0aa",
  "currency": "EUR",
  "status": "frozen",
  "statusReason": "Chargeback opened on the last top-up",
  "statusChangedAt": "2026-10-16T10:15:00.000Z",
  "available": {
    "amount": "77000000",
    "currency": "EUR"
  },
  "promo": {
    "amount": "5000000",
    "currency": "EUR"
  },
  "reserved": {
    "amount": "3000000",
    "currency": "EUR"
  },
  "balance": {
    "amount": "85000000",
    "currency": "EUR"
  },
  "lowBalanceThreshold": {
    "amount": "10000000",
    "currency": "EUR"
  },
  "lowBalance": false,
  "autoReload": null,
  "createdAt": "2026-10-14T09:00:00.000Z",
  "updatedAt": "2026-10-16T10:15:00.000Z",
  "upcomingExpiries": [
    {
      "grantId": "grant_01m4ty7w2a5qx7mhd9k8w6s0b3",
      "source": "promo",
      "remaining": {
        "amount": "5000000",
        "currency": "EUR"
      },
      "expiresAt": "2026-11-01T00:00:00.000Z"
    }
  ]
}