docs/developer/sdk/configuration.mdx
import LocalizationExample from '/snippets/store-api/localization-example.mdx'
Pass locale and currency headers with any request. For full details, see the Localization reference.
<LocalizationExample />// Works with all endpoints
const category = await client.categories.get('clothing/shirts', {
expand: ['ancestors'],
}, {
locale: 'de',
currency: 'EUR',
})
import { SpreeError } from '@spree/sdk';
try {
await client.products.get('non-existent');
} catch (error) {
if (error instanceof SpreeError) {
console.log(error.code); // 'record_not_found'
console.log(error.message); // 'Product not found'
console.log(error.status); // 404
console.log(error.details); // Validation errors (if any)
}
}
You can provide a custom fetch implementation:
import { createClient } from '@spree/sdk';
const client = createClient({
baseUrl: 'https://api.mystore.com',
publishableKey: 'pk_xxx',
fetch: customFetchImplementation,
});
All monetary values in the API are returned as strings (e.g., "29.99", "0.0"), not numbers. This preserves decimal precision and avoids floating-point rounding issues.
const order = await client.orders.get('or_abc123', {}, { token });
// Monetary fields are strings
order.total; // "129.99"
order.item_total; // "99.99"
order.delivery_total; // "10.00"
order.tax_total; // "20.00"
// Display fields include currency formatting
order.display_total; // "$129.99"
// Convert to number when needed for calculations
const total = parseFloat(order.total);
This applies to all monetary fields across all types: Order, LineItem, Fulfillment, Payment, GiftCard, Price, etc.
The SDK includes full TypeScript support with generated types from the API serializers:
import type {
Product,
Order,
Cart,
Variant,
Category,
LineItem,
Address,
Customer,
PaginatedResponse,
} from '@spree/sdk';
// All responses are fully typed
const products: PaginatedResponse<Product> = await client.products.list();
const category: Category = await client.categories.get('clothing');
All types are exported as unprefixed names (e.g., Product, Order). Legacy Store* prefixed aliases (e.g., StoreProduct) are still available for backward compatibility.
Product - Product dataVariant - Variant dataCart - Cart data (uses cart_ prefixed IDs)Order - Completed order data (uses or_ prefixed IDs)LineItem - Line item in cartCategory - CategoryCountry - Country with statesState - State/provinceAddress - Customer addressCustomer - Customer profileMarket - Market configuration (currency, locales, countries)Payment - Payment recordPaymentMethod - Payment methodPaymentSession - Provider-agnostic payment sessionFulfillment - Fulfillment recordDeliveryRate - Delivery rate optionDeliveryMethod - Delivery methodCreditCard - Saved credit cardGiftCard - Gift cardDiscount - Discount applied to a cart or orderMedia - Product media (images, videos)Price - Price dataOptionType - Option type (e.g., Size, Color)OptionValue - Option value (e.g., Small, Red)DigitalLink - Digital download linkMetafield - Custom metafield dataWishlist - WishlistWishlistItem - Wishlist itemClient - Main client interfaceStoreClient - Store API client classClientConfig - Client configurationRequestOptions - Per-request optionsRetryConfig - Retry behavior configurationPaginatedResponse<T> - Paginated API responseListResponse<T> - List API responseAuthTokens - JWT tokens from loginAddressParams - Address input parametersUpdateCartParams - Cart update parametersCreatePaymentParams - Direct payment creation parametersCreatePaymentSessionParams - Payment session creation parametersUpdatePaymentSessionParams - Payment session update parametersCompletePaymentSessionParams - Payment session completion parametersProductFiltersResponse - Product filters responseCheckoutRequirement - Checkout requirement ({ step, field, message })All generated SDK types are TypeScript interfaces, which means you can extend them via declaration merging when you customize API serializers on the backend.
If you've customized the ProductSerializer in your app to include a brand_id attribute:
# app/serializers/my_store/product_serializer.rb
module MyStore
class ProductSerializer < Spree::Api::V3::ProductSerializer
typelize brand_id: :string
attribute :brand_id do |product|
product.brand&.prefixed_id
end
end
end
# config/initializers/spree.rb
Spree.api.product_serializer = MyStore::ProductSerializer
You can extend the SDK type in your frontend code so TypeScript knows about the new field:
// types/spree.d.ts
declare module '@spree/sdk' {
interface Product {
brand_id: string;
}
}
Now brand_id is available on every Product across your app — no type casting needed:
const products = await client.products.list();
products.data.forEach((product) => {
console.log(product.brand_id); // fully typed
});
If you use the SDK's Zod schemas for runtime validation, extend them with .extend():
import { z } from 'zod';
import { ProductSchema } from '@spree/sdk/zod';
const MyProductSchema = ProductSchema.extend({
brand_id: z.string(),
});
// Use for runtime validation
const product = MyProductSchema.parse(apiResponse);