Skip to content

Update a wallet's settings or status

The wallets.update operation: PATCH /api/v1/wallets/{id} in the REST API and the wallets_update tool in the MCP server.

PATCH/api/v1/wallets/{id}

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.

At a glance

  • REST: PATCH /api/v1/wallets/{id}
  • MCP tool: wallets_update
  • Operation ID: wallets.update
  • Scope: Brand
  • Permission: wallets:write
  • Risk tier: write
  • Dry run: Supported (send Ownrecord-Dry-Run: true)
  • Idempotency: Idempotency-Key optional
  • Modes: Test and live
  • Authentication: API key with the wallets:write scope
  • Since: M6

Request

Path parameters

FieldTypeDescription
idwal_… IDThe wallet (wal_…).

Body

A JSON object (Content-Type: application/json):

FieldTypeRequiredDescription
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.

Response

200 OK with a JSON object:

FieldTypeDescription
idwal_… ID
object"wallet"
brandIdbrd_… ID
livemodeboolean
customerIdcus_… ID
currencystring
statusone of active, frozen, closedactive, frozen (no new reservations or leases) or closed (retired; reopened by a purchase).
statusReasonstring or nullWhy the wallet is frozen or closed.
statusChangedAtdate-time or null
availablemoneySpendable purchased, subscription and adjustment credits (not reserved). Expired credits stay here until the hourly expiry job takes them out.
promomoneySpendable promo credits (spent first; never refundable).
reservedmoneyHeld by open reservations and leases.
balancemoneyAll unspent credits: available + promo + reserved.
lowBalanceThresholdmoney or null
lowBalancebooleanThe balance is below lowBalanceThreshold.
autoReloadobject or null
upcomingExpiriesarray of objectThe next grants to expire (at most 10), soonest first.
upcomingExpiries[].grantIdgrant_… ID
upcomingExpiries[].sourceone of purchase, subscription, promo, adjustment, refund_reversal
upcomingExpiries[].remainingmoneyWhat is left of the grant; whatever is unused at expiresAt expires.
upcomingExpiries[].expiresAtdate-time
createdAtdate-time
updatedAtdate-time

Examples

Warn below €10 and reload €50 below €10

HTTP
PATCH /api/v1/wallets/wal_01m4ty7w2a5qx7mhd9k8w6s0b1
Authorization: Bearer or_test_…
Content-Type: application/json

{
  "lowBalanceThreshold": {
    "amount": "10000000",
    "currency": "EUR"
  },
  "autoReload": {
    "enabled": true,
    "below": {
      "amount": "10000000",
      "currency": "EUR"
    },
    "amount": {
      "amount": "50000000",
      "currency": "EUR"
    },
    "paymentMethodId": "pm_01m4ty7w2a5qx7mhd9k8w6s0b6"
  }
}

Response (200):

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

HTTP
PATCH /api/v1/wallets/wal_01m4ty7w2a5qx7mhd9k8w6s0b1
Authorization: Bearer or_test_…
Content-Type: application/json

{
  "status": "frozen",
  "reason": "Chargeback opened on the last top-up"
}

Response (200):

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"
    }
  ]
}

Errors

CodeHTTP statusWhenWhat to do
validation_failed400Nothing to change, an amount isn't positive (or a reload amount isn't whole minor units), or reason is missing when freezing or closing.Fix the fields listed in details.issues and send the request again.
resource_not_found404This brand has no such wallet in this mode (wallets belong to one brand and one mode).Check the ID and that your credentials are scoped to the right organization, entity, brand and mode.
wallet_currency_mismatch400A threshold or reload amount isn't in the wallet's currency.Use the wallet for this currency. A customer has one wallet per currency (details.expected, details.actual).
wallet_payment_method_invalid400Auto-reload is enabled with a payment method that isn't the customer's, or was detached.Use a saved payment method (pm_…) of the wallet's customer that isn't detached. Customers save one at a subscription or setup checkout.
wallet_not_empty409The wallet is closed while it still has credits or open reservations (details.balance, details.open_reservations).Capture or release its open reservations and wait until its credits are used or expire (details.balance in integer micros, details.open_reservations). To stop spending at once, freeze it instead.
wallet_closed409A closed wallet is frozen: reopen it first (status: active).Reopen the wallet with wallets.update (status: active). A purchase of credits in its currency reopens it, too.
version_conflict409The wallet changed at the same moment (another reservation, capture or grant); retry.Fetch the object again and retry the change.
scope_required400The request names no brand (an org or entity key without Ownrecord-Brand).Call the operation with credentials or a target at its level: an organization, a legal entity, a brand or the platform (details.required_scope).
permission_denied403You can't change this brand's wallets (wallets:write: owners, admins and support).Ask an organization owner or admin for a role or scope that allows this action.
livemode_not_allowed403You have no live-mode access, so you can't use live wallets.Use test mode, or credentials for the target's mode. Developers need live access granted by an organization owner or admin.

It can also return these common errors: api_version_unsupported, invalid_json, unsupported_media_type, authentication_required, api_key_invalid, idempotency_key_reused, idempotency_in_progress, approval_required, approval_rejected, approval_expired, stale_approval, approval_policy_denied, rate_limited, internal_error.