Store API
WalletPro extends the WooCommerce Store API (wc/store/v1) with a wallet namespace that exposes balance, top-up, and redemption data to Blocks-based checkouts and headless storefronts. This lets any client that can reach the Store API read a customer's wallet balance and apply wallet payments without coupling to the legacy shortcode checkout.
Overview
The WooCommerce Store API (/wp-json/wc/store/v1/) is the API surface consumed by the Blocks-based Cart and Checkout and by headless frontends. It is distinct from the authenticated Admin REST API (/wp-json/wc/v3/). WalletPro registers its extension into this namespace using WooCommerce's ExtendSchema mechanism, which injects namespaced data into existing endpoints without creating naming conflicts with other plugins.
WalletPro's Store API extension does two things:
- Injects wallet data (balance, currency, redemption eligibility) into the
wc/store/v1/cartandwc/store/v1/checkoutresponse objects under theextensions.walletprokey. - Registers dedicated routes under
wc/store/v1/walletpro/for balance lookup, coupon/code redemption, and top-up initiation.
The Store API is session-authenticated via nonce tokens. Customers do not need an API key. All wallet mutations require a valid Nonce Token passed in the Nonce request header or as the _wpnonce query parameter.
Authentication
Store API endpoints use the same nonce-based authentication as the core WooCommerce Store API. Obtain a nonce by calling the standard WooCommerce nonce endpoint or by reading the woocommerce-store-api-nonce value emitted in the page HTML by the Blocks runtime.
| Header | Value | Required |
|---|---|---|
Nonce |
WooCommerce Store API nonce | Required for write operations |
Content-Type |
application/json |
Required for POST/PUT bodies |
X-WP-Nonce |
WordPress REST nonce (admin-ajax route) | Optional fallback for non-Blocks clients |
GET requests to balance endpoints use the active customer session cookie; no nonce is required to read balance.
Cart and Checkout Extension Data
WalletPro injects wallet context into the core cart and checkout responses. This data appears under response.extensions.walletpro and is available to custom Blocks, SlotFills, and headless clients reading these endpoints.
Extended Cart Response
Endpoint: GET /wp-json/wc/store/v1/cart
// Response, extensions key added by WalletPro
{
"totals": { /* standard WooCommerce cart totals */ },
"extensions": {
"walletpro": {
"balance": "42.50",
"balance_minor": 4250,
"currency_code": "USD",
"currency_symbol": "$",
"can_pay_full": true,
"can_pay_partial": true,
"applicable_amount": "29.99",
"spending_limit": "100.00",
"spending_limit_remaining_today": "57.50",
"wallet_enabled": true,
"gateway_id": "walletpro"
}
}
}
Extended Checkout Response
Endpoint: GET /wp-json/wc/store/v1/checkout
{
"order_id": 0,
"extensions": {
"walletpro": {
"balance": "42.50",
"balance_minor": 4250,
"step_up_required": false,
"step_up_threshold": "50.00",
"redemption_code_accepted": false,
"redemption_code_value": null
}
}
}
Extension Schema Fields
| Field | Type | Description |
|---|---|---|
balance |
string | Formatted decimal balance in the wallet's currency. |
balance_minor |
integer | Balance in minor units (cents). Use this for arithmetic to avoid float rounding. |
currency_code |
string | ISO 4217 currency code for this wallet. |
can_pay_full |
boolean | true when wallet balance covers the entire cart total. |
can_pay_partial |
boolean | true when partial wallet payment is enabled and balance is positive. |
applicable_amount |
string | The amount WalletPro will deduct at checkout, after spending-limit and velocity-cap checks. |
spending_limit |
string | Maximum wallet spend per transaction configured in WooCommerce > WalletPro > Limits. |
step_up_required |
boolean | true when the order total exceeds the step-up authentication threshold. |
wallet_enabled |
boolean | false when the wallet gateway is disabled or KYC is incomplete. |
gateway_id |
string | The payment gateway ID to submit as payment_method to the checkout endpoint. |
Dedicated WalletPro Routes
These routes are registered under the Store API namespace. They follow the same nonce-based auth model as core Store API endpoints.
GET /wp-json/wc/store/v1/walletpro/balance
Returns the current customer's wallet balance. Uses the active session; no nonce required.
// Request
GET /wp-json/wc/store/v1/walletpro/balance
// Response 200
{
"balance": "42.50",
"balance_minor": 4250,
"currency_code": "USD",
"currency_symbol": "$",
"currency_minor_unit": 2,
"formatted": "$42.50"
}
Response codes: 200 OK | 401 Unauthorized (guest with no session) | 403 Forbidden (KYC gate active)
POST /wp-json/wc/store/v1/walletpro/apply-redemption
Validates and applies a redemption code to the current cart session. The code is consumed on successful payment; calling this endpoint only marks it as pending.
| Parameter | Type | Required | Description |
|---|---|---|---|
code |
string | Required | The alphanumeric redemption code entered by the customer. |
// Request
POST /wp-json/wc/store/v1/walletpro/apply-redemption
Nonce: <store-api-nonce>
Content-Type: application/json
{
"code": "WELCOME25"
}
// Response 200, code valid
{
"applied": true,
"code": "WELCOME25",
"credit_amount": "25.00",
"credit_amount_minor": 2500,
"expires_at": null,
"message": "Code applied. $25.00 will be credited to your wallet on order completion."
}
// Response 422, code invalid or exhausted
{
"code": "walletpro_invalid_code",
"message": "This redemption code is invalid or has already been used.",
"data": { "status": 422 }
}
DELETE /wp-json/wc/store/v1/walletpro/apply-redemption
Removes a previously applied redemption code from the current cart session without consuming it.
DELETE /wp-json/wc/store/v1/walletpro/apply-redemption
Nonce: <store-api-nonce>
// Response 200
{ "removed": true }
POST /wp-json/wc/store/v1/walletpro/topup/initiate
Initiates a wallet top-up order for the authenticated customer. Returns a checkout URL the client should redirect to, or a payment intent object for embedded payment UIs.
| Parameter | Type | Required | Description |
|---|---|---|---|
amount |
string | Required | Decimal top-up amount in the store's base currency (e.g., "50.00"). |
payment_method |
string | Optional | Gateway ID to use. Defaults to the store's default payment method. |
return_url |
string | Optional | URL to redirect to after payment. Defaults to the WalletPro My Account tab. |
// Request
POST /wp-json/wc/store/v1/walletpro/topup/initiate
Nonce: <store-api-nonce>
Content-Type: application/json
{
"amount": "50.00",
"payment_method": "stripe",
"return_url": "https://example.com/my-account/wallet/"
}
// Response 200
{
"order_id": 1842,
"checkout_url": "https://example.com/checkout/order-pay/1842/?key=wc_order_xKF7...",
"amount": "50.00",
"currency_code": "USD"
}
Registering Your Own Extension Data
If you are building a custom Block or headless feature that needs to read WalletPro data alongside your own plugin data, you can register an additional ExtendSchema endpoint on top of WalletPro's. The two namespaces are independent and both appear under extensions.
To extend the cart or checkout endpoint from your own plugin:
use Automattic\WooCommerce\StoreApi\StoreApi;
use Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema;
use Automattic\WooCommerce\StoreApi\Schemas\V1\CartSchema;
add_action( 'woocommerce_blocks_loaded', function() {
$extend = StoreApi::container()->get( ExtendSchema::class );
$extend->register_endpoint_data([
'endpoint' => CartSchema::IDENTIFIER,
'namespace' => 'my_plugin',
'data_callback' => function() {
// Return data to inject under extensions.my_plugin
return [ 'loyalty_tier' => get_user_meta( get_current_user_id(), 'loyalty_tier', true ) ];
},
'schema_callback' => function() {
return [
'loyalty_tier' => [
'description' => 'Customer loyalty tier',
'type' => 'string',
'context' => [ 'view', 'edit' ],
'readonly' => true,
'optional' => true,
],
];
},
'schema_type' => ARRAY_A,
]);
} );
The resulting cart response will contain both extensions.walletpro and extensions.my_plugin independently.
Applying Wallet Payment at Checkout
To charge a customer's wallet via the Blocks checkout, set payment_method to "walletpro" in the POST body sent to wc/store/v1/checkout. WalletPro's payment gateway handles the debit atomically during order processing.
// Full wallet payment
POST /wp-json/wc/store/v1/checkout
Nonce: <store-api-nonce>
Content-Type: application/json
{
"billing_address": {
"first_name": "Jane",
"last_name": "Smith",
"email": "jane@example.com",
"address_1": "123 Main St",
"city": "Portland",
"state": "OR",
"postcode": "97201",
"country": "US"
},
"shipping_address": { /* same shape */ },
"payment_method": "walletpro",
"payment_data": [
{ "key": "walletpro_apply_full", "value": true }
]
}
// Response 200
{
"order_id": 1899,
"status": "processing",
"payment_result": {
"payment_status": "success",
"redirect_url": "https://example.com/checkout/order-received/1899/"
},
"extensions": {
"walletpro": {
"deducted_amount": "29.99",
"balance_after": "12.51",
"balance_after_minor": 1251
}
}
}
Partial Payment
When the cart total exceeds the wallet balance and partial payment is enabled (WooCommerce > WalletPro > Checkout > Allow partial payment), submit both a wallet and a second gateway:
{
"payment_method": "walletpro",
"payment_data": [
{ "key": "walletpro_apply_partial", "value": true },
{ "key": "walletpro_secondary_gateway", "value": "stripe" },
{ "key": "walletpro_secondary_payment_data", "value": { "stripe_payment_method": "pm_..." } }
]
}
When Step-Up Authentication is enabled (WooCommerce > WalletPro > Security > Step-up threshold), orders at or above the threshold return extensions.walletpro.step_up_required: true in the GET checkout response. The client must collect the customer's wallet PIN or OTP and pass it as walletpro_step_up_token in payment_data before the POST will succeed.
Configuration
The Store API extension is active automatically when WalletPro is installed. The following settings in WooCommerce > WalletPro > Checkout affect Store API behavior:
| Setting | Path | Effect on Store API |
|---|---|---|
| Enable wallet payment | WooCommerce > WalletPro > Checkout | Controls wallet_enabled in extension data. When off, the walletpro gateway is hidden from available payment methods. |
| Allow partial payment | WooCommerce > WalletPro > Checkout | Controls can_pay_partial. When off, partial payment payment_data keys are rejected with 400. |
| Per-transaction spending limit | WooCommerce > WalletPro > Limits | Caps applicable_amount and spending_limit fields. |
| Step-up threshold | WooCommerce > WalletPro > Security | Sets the order total above which step_up_required returns true. |
| Redemption codes | WooCommerce > WalletPro > Redemption Codes | Must be enabled for the /apply-redemption route to accept codes. Rate-limit settings apply per customer session. |
| KYC gate | WooCommerce > WalletPro > Compliance | When KYC is required and incomplete, wallet_enabled returns false and balance routes return 403. |
Error Codes
All WalletPro Store API errors follow the WooCommerce Store API error envelope format: {"code": "...", "message": "...", "data": {"status": NNN}}.
| Error Code | HTTP Status | Description |
|---|---|---|
walletpro_insufficient_balance |
422 | Wallet balance is less than the amount being debited and partial payment is not allowed. |
walletpro_spending_limit_exceeded |
422 | The requested debit exceeds the per-transaction or daily spending limit. |
walletpro_step_up_required |
403 | Order total meets the step-up threshold; a step-up token must be provided. |
walletpro_step_up_invalid |
403 | The step-up token provided is incorrect or expired. |
walletpro_invalid_code |
422 | Redemption code is not found, already used, or expired. |
walletpro_code_rate_limited |
429 | Too many redemption code attempts in the configured window. |
walletpro_kyc_required |
403 | Customer has not completed KYC verification. |
walletpro_wallet_disabled |
403 | The wallet gateway is disabled in WalletPro settings. |
walletpro_concurrent_debit |
409 | A concurrent debit on the same wallet was detected. Retry after a short delay. |
WalletPro debits are atomic and HMAC-chained in the audit ledger. If a payment attempt returns 409 walletpro_concurrent_debit, it means the previous transaction has not yet committed. Retry the POST to /wc/store/v1/checkout once; do not create a new order.
JavaScript Usage Example
The following snippet shows how a custom Block inner component reads wallet balance from the cart extensions and displays it, using the WooCommerce Blocks @woocommerce/block-data store.
import { useSelect } from '@wordpress/data';
import { CART_STORE_KEY } from '@woocommerce/block-data';
const WalletBalance = () => {
const walletExtensions = useSelect( ( select ) => {
const cart = select( CART_STORE_KEY ).getCartData();
return cart?.extensions?.walletpro ?? null;
} );
if ( !walletExtensions?.wallet_enabled ) return null;
return (
<div className="walletpro-balance-display">
Wallet balance: { walletExtensions.formatted }
{ walletExtensions.can_pay_full && (
<span>, covers this order in full</span>
) }
</div>
);
};
Compatibility Notes
- The Store API extension requires WooCommerce 8.2 or later and the Blocks package bundled with it. It does not require the standalone Blocks plugin.
- HPOS (High-Performance Order Storage) is supported. All order reads and writes in WalletPro Store API routes use the
OrderUtilabstraction. - Multi-currency wallets: if a customer holds balances in multiple currencies, the balance returned in extension data matches the currency of the current cart. Use the
/balanceroute directly to query other currency balances. - The Store API extension is independent of the WalletPro Admin REST API (
walletpro/v1). Store API routes use session auth; Admin REST API routes require application passwords or OAuth.