@spree/docs 0.1.88 → 0.1.89

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -337,7 +337,9 @@ cd packages/sdk # or packages/admin-sdk, packages/cli, packages/create-spree-
337
337
  pnpm changeset
338
338
  ```
339
339
 
340
- This creates a changeset file describing your changes. Commit it with your PR. When merged to `main`, a GitHub Action creates a "Version Packages" PR that bumps the version and publishes to npm.
340
+ This creates a changeset file describing your changes. Commit it with your PR.
341
+
342
+ Releasing is a two-step flow: a maintainer consumes the pending changesets (`changeset version` — writes the CHANGELOG and bumps `package.json`) and merges that bump to `main`; the release jobs in `.github/workflows/packages.yml` then detect the unpublished version and publish with npm provenance via Trusted Publishing. `@spree/admin-sdk` publishes under the `next` dist-tag while on the 0.x Developer Preview line; the others ship as `latest` (prereleases go to `beta`).
341
343
 
342
344
  Private packages (`@spree/dashboard`, `@spree/dashboard-core`, `@spree/dashboard-ui`, `@spree/sdk-core`) don't need changesets.
343
345
 
@@ -0,0 +1,108 @@
1
+ ---
2
+ title: "Authentication"
3
+ description: "Authenticate the Admin SDK with a secret API key (server-to-server, scope-based) or JWT cookie auth (browser admin apps, role-based)."
4
+ ---
5
+
6
+ The Admin API supports two authentication methods. Both reach the same endpoints — they differ in **where the credential lives** and **how authorization is decided**:
7
+
8
+ | | Secret API key | JWT + cookie |
9
+ |---|---|---|
10
+ | **For** | Backend integrations, automations, cron jobs | Browser-based admin apps where a human signs in |
11
+ | **Credential** | `sk_…` key, created in the admin | Short-lived access token + httpOnly refresh cookie |
12
+ | **Authorization** | [Scopes](../../../api-reference/admin-api/authentication.md) attached to the key (`read_products`, `write_orders`, …) | The admin user's roles and permissions |
13
+ | **Where it runs** | Server-side only — never in a browser | Browser (the refresh token never touches your JS) |
14
+
15
+ ## Secret API key (server-to-server)
16
+
17
+ Create a secret key in the admin under **Settings → API Keys**, grant it the scopes your integration needs, and pass it to the client:
18
+
19
+ ```typescript
20
+ import { createAdminClient } from '@spree/admin-sdk'
21
+
22
+ const client = createAdminClient({
23
+ baseUrl: 'https://your-store.com',
24
+ secretKey: process.env.SPREE_SECRET_KEY, // sk_xxx
25
+ })
26
+ ```
27
+
28
+ Each key carries the list of scopes granted at creation time. A request to an endpoint the key isn't scoped for fails with `code: 'access_denied'` — the error's `details.required_scope` names the missing scope (see [Querying & Errors](querying-and-errors.md#scope-errors)).
29
+
30
+ > **WARNING:** Secret keys grant back-office access to your store. Never embed them in client-side code, mobile apps, or public repositories — keep them in server-side environment variables or a secrets manager.
31
+
32
+ ## JWT + cookie authentication (browser apps)
33
+
34
+ For browser-based admin tooling, authenticate as an admin user. The flow is designed so that **no long-lived credential is ever exposed to JavaScript**:
35
+
36
+ - `auth.login()` returns `{ token, user }` — a short-lived access token you hold in memory.
37
+ - The **refresh token never appears in JSON.** The server sets it as an `HttpOnly` cookie scoped to `/api/v3/admin/auth`, and the SDK sends requests with `credentials: 'include'` by default, so the cookie flows automatically.
38
+ - `auth.refresh()` takes **no arguments** — it's driven entirely by the cookie, and rotates it on every call.
39
+ - `auth.logout()` revokes the refresh token server-side and clears the cookie.
40
+
41
+ ```typescript
42
+ import { createAdminClient } from '@spree/admin-sdk'
43
+
44
+ // A cookie-auth app can start with no credentials at all
45
+ const client = createAdminClient({ baseUrl: 'https://your-store.com' })
46
+
47
+ // Sign in — the refresh token lands in the httpOnly cookie
48
+ const { token, user } = await client.auth.login({
49
+ email: 'admin@example.com',
50
+ password: 'password123',
51
+ })
52
+ client.setToken(token)
53
+
54
+ // Auto-recover from expired access tokens
55
+ client.onUnauthorized(async () => {
56
+ const { token: fresh } = await client.auth.refresh()
57
+ client.setToken(fresh)
58
+ return true // retry the failed request
59
+ })
60
+
61
+ // Sign out — revokes the refresh token server-side
62
+ await client.auth.logout()
63
+ ```
64
+
65
+ ### Bootstrapping a returning session
66
+
67
+ Because the refresh cookie outlives the in-memory access token, a returning user can be signed back in without re-entering credentials — call `refresh()` on app load and treat failure as "not signed in":
68
+
69
+ ```typescript
70
+ try {
71
+ const { token } = await client.auth.refresh()
72
+ client.setToken(token)
73
+ } catch {
74
+ // No valid session — show the login form
75
+ }
76
+ ```
77
+
78
+ ### Identity providers
79
+
80
+ `auth.login()` also accepts third-party identity-provider payloads when the server has a matching strategy registered in `Spree.store_authentication_strategies`:
81
+
82
+ ```typescript
83
+ const { token } = await client.auth.login({ provider: 'auth0', token: idpJwt })
84
+ ```
85
+
86
+ ### Current user and permissions
87
+
88
+ After signing in, `client.me.get()` returns the admin user's profile together with their serialized permissions — use it to drive what your UI shows:
89
+
90
+ ```typescript
91
+ const { user, permissions } = await client.me.get()
92
+ ```
93
+
94
+ ## Staff invitations
95
+
96
+ The `auth` resource also exposes the unauthenticated invitation-acceptance flow used when onboarding new staff: `auth.lookupInvitation(id, token)` returns the safe-to-render invitation context (store, role, inviter), and `auth.acceptInvitation(id, token, params)` accepts it — issuing a JWT and refresh cookie identical to `login`. Sending invitations is an authenticated operation on [`client.invitations`](resources.md).
97
+
98
+ ## Custom fetch
99
+
100
+ Pass a custom `fetch` implementation when you need request interception, proxying, or a non-standard runtime:
101
+
102
+ ```typescript
103
+ const client = createAdminClient({
104
+ baseUrl: 'https://your-store.com',
105
+ secretKey: process.env.SPREE_SECRET_KEY,
106
+ fetch: customFetchImplementation,
107
+ })
108
+ ```
@@ -0,0 +1,129 @@
1
+ ---
2
+ title: "Querying & Errors"
3
+ description: "Filter, sort, paginate, and expand Admin API collections with flat Ransack parameters — and handle structured SpreeError responses."
4
+ ---
5
+
6
+ ## Filtering
7
+
8
+ Collection endpoints support [Ransack](https://activerecord-hackery.github.io/ransack/) filters passed as **flat parameters** — append a predicate suffix to any filterable attribute. The SDK wraps filter keys in `q[…]` automatically:
9
+
10
+ ```typescript
11
+ const { data: orders } = await client.orders.list({
12
+ status_eq: 'complete', // exact match
13
+ total_gteq: 100, // greater than or equal
14
+ email_cont: '@example.com', // substring match
15
+ user_id_eq: 'cus_xxx', // prefixed IDs work directly
16
+ sort: '-completed_at',
17
+ page: 2,
18
+ limit: 50,
19
+ })
20
+ ```
21
+
22
+ Common predicates: `_eq`, `_not_eq`, `_cont` (contains), `_start`, `_end`, `_gteq` / `_lteq`, `_gt` / `_lt`, `_in` (array), `_null`. The filterable attributes per resource are listed in the [Admin API reference](../../../api-reference/admin-api/introduction.md); each model declares an explicit allowlist, so unknown filter keys are ignored rather than executed.
23
+
24
+ > **NOTE:** Foreign-key predicates accept **prefixed IDs** (`user_id_eq: 'cus_xxx'`, `variant_id_in: ['variant_a', 'variant_b']`) — the API translates them; you never handle raw database IDs.
25
+
26
+ ## Sorting
27
+
28
+ Pass `sort` with an attribute name; prefix with `-` for descending. Comma-separate multiple fields:
29
+
30
+ ```typescript
31
+ await client.products.list({ sort: '-updated_at,name' })
32
+ ```
33
+
34
+ ## Pagination
35
+
36
+ List responses return `{ data, meta }`. Drive pagination with `page` and `limit`:
37
+
38
+ ```typescript
39
+ const { data, meta } = await client.products.list({ page: 1, limit: 50 })
40
+
41
+ meta.count // total records
42
+ meta.pages // total pages
43
+ meta.next // next page number, or null on the last page
44
+ meta.previous // previous page number, or null on the first
45
+ ```
46
+
47
+ A simple fetch-all loop:
48
+
49
+ ```typescript
50
+ let page: number | null = 1
51
+ while (page) {
52
+ const { data, meta } = await client.products.list({ page, limit: 100 })
53
+ process(data)
54
+ page = meta.next
55
+ }
56
+ ```
57
+
58
+ ## Expanding associations
59
+
60
+ Pass `expand` to embed related records in the response, instead of making follow-up requests. Dot notation reaches nested associations (up to 4 levels):
61
+
62
+ ```typescript
63
+ const order = await client.orders.get('order_xxx', {
64
+ expand: ['items', 'customer', 'fulfillments.items'],
65
+ })
66
+
67
+ const products = await client.products.list({
68
+ expand: ['variants', 'variants.media'],
69
+ })
70
+ ```
71
+
72
+ `fields` does the opposite — trims the response to just the attributes you name (`id` is always included):
73
+
74
+ ```typescript
75
+ await client.products.list({ fields: ['name', 'slug', 'status'] })
76
+ ```
77
+
78
+ ## Error handling
79
+
80
+ Every non-2xx response throws a `SpreeError` with a stable machine-readable `code`, the HTTP `status`, and optional structured `details`:
81
+
82
+ ```typescript
83
+ import { SpreeError } from '@spree/admin-sdk'
84
+
85
+ try {
86
+ await client.orders.update(orderId, { email })
87
+ } catch (err) {
88
+ if (err instanceof SpreeError) {
89
+ err.code // e.g. 'validation_error', 'record_not_found', 'access_denied'
90
+ err.status // e.g. 422
91
+ err.message // human-readable summary
92
+ err.details // optional structured context
93
+ }
94
+ }
95
+ ```
96
+
97
+ ### Validation errors
98
+
99
+ On `422` responses, `details` maps attribute names to arrays of messages — ready to project onto form fields:
100
+
101
+ ```typescript
102
+ try {
103
+ await client.products.create({ name: '' })
104
+ } catch (err) {
105
+ if (err instanceof SpreeError && err.status === 422) {
106
+ err.details // { name: ["can't be blank"] }
107
+ }
108
+ }
109
+ ```
110
+
111
+ ### Scope errors
112
+
113
+ When a request fails because the secret API key lacks the required [scope](authentication.md), the error has `code: 'access_denied'` and `details.required_scope` names the missing scope:
114
+
115
+ ```typescript
116
+ catch (err) {
117
+ if (err instanceof SpreeError && err.code === 'access_denied') {
118
+ console.error(`API key is missing scope: ${err.details?.required_scope}`)
119
+ }
120
+ }
121
+ ```
122
+
123
+ ### Expired JWT sessions
124
+
125
+ For cookie-authenticated apps, register an `onUnauthorized` handler to transparently refresh and retry on `401` — see [Authentication](authentication.md#jwt--cookie-authentication-browser-apps).
126
+
127
+ ## Retries
128
+
129
+ The SDK retries failed idempotent requests (GET/HEAD, plus requests carrying an idempotency key) with exponential backoff and jitter — transient network errors and retryable statuses recover without any code on your side.
@@ -1,22 +1,69 @@
1
1
  ---
2
- title: Admin API
3
- description: Manage your store programmatically with the Spree Admin SDK
2
+ title: "Admin SDK"
3
+ sidebarTitle: Quickstart
4
+ description: "Manage your store programmatically with @spree/admin-sdk — the official TypeScript client for the Spree Admin API v3."
4
5
  ---
5
6
 
6
- > **INFO:** The Admin API SDK is coming soon. The `client.admin` namespace is ready and will provide full access to administrative endpoints for managing products, orders, customers, and store settings.
7
+ [`@spree/admin-sdk`](https://www.npmjs.com/package/@spree/admin-sdk) is the official TypeScript SDK for the [Admin API v3](../../../api-reference/admin-api/introduction.md) the back-office counterpart to [`@spree/sdk`](../quickstart.md). Use it to build integrations, automations, internal tools, and custom admin UIs: manage products, orders, customers, stock, promotions, webhooks, and more.
7
8
 
8
- ## Preview
9
+ > **WARNING:** The Admin SDK is in **Developer Preview** on the `0.x` line and published under the `next` dist-tag. The API surface may change between minor versions — check the [changelog](https://github.com/spree/spree/blob/main/packages/admin-sdk/CHANGELOG.md) when updating. It requires Spree 5.5 or newer.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @spree/admin-sdk@next
15
+ ```
16
+
17
+ ## Quick start
18
+
19
+ Create a client with a [secret API key](authentication.md) (server-to-server) and start calling resources:
9
20
 
10
21
  ```typescript
11
- import { createClient } from '@spree/sdk';
22
+ import { createAdminClient } from '@spree/admin-sdk'
12
23
 
13
- const client = createClient({
14
- baseUrl: 'https://api.mystore.com',
15
- secretKey: 'sk_xxx', // Admin API requires a secret key
16
- });
24
+ const client = createAdminClient({
25
+ baseUrl: 'https://your-store.com',
26
+ secretKey: process.env.SPREE_SECRET_KEY, // sk_xxx server-side only
27
+ })
17
28
 
18
- // Admin endpoints will be available under client.admin.*
19
- // client.admin.products.list()
20
- // client.admin.orders.list()
21
- // client.admin.customers.list()
29
+ // List recent completed orders
30
+ const { data: orders, meta } = await client.orders.list({
31
+ status_eq: 'complete',
32
+ sort: '-completed_at',
33
+ limit: 25,
34
+ })
35
+
36
+ // Create a purchasable product — pricing lives on variants
37
+ const product = await client.products.create({
38
+ name: 'Aero Hoodie',
39
+ status: 'active',
40
+ tags: ['new-arrivals'],
41
+ variants: [
42
+ {
43
+ sku: 'AERO-HOODIE',
44
+ prices: [{ currency: 'USD', amount: '59.00' }],
45
+ },
46
+ ],
47
+ })
22
48
  ```
49
+
50
+ Every method is fully typed — responses use `Admin`-prefixed types generated from the API serializers:
51
+
52
+ ```typescript
53
+ import type { AdminOrder, PaginatedResponse } from '@spree/admin-sdk'
54
+
55
+ const page: PaginatedResponse<AdminOrder> = await client.orders.list()
56
+ ```
57
+
58
+ > **NOTE:** Secret keys grant back-office access — never ship them in browser code. For browser-based admin apps, use [JWT cookie authentication](authentication.md#jwt--cookie-authentication-browser-apps) instead.
59
+
60
+ ## Learn more
61
+
62
+
63
+ - [Authentication](authentication.md) — Secret keys with scopes for servers, JWT + httpOnly refresh cookie for browser apps.
64
+ - [Resources](resources.md) — The full resource map — products, orders, customers, stock, promotions, webhooks, and more.
65
+ - [Querying & Errors](querying-and-errors.md) — Filtering, sorting, pagination, prefixed IDs, and structured error handling.
66
+ - [Admin API Reference](../../../api-reference/admin-api/introduction.md) — The underlying REST API the SDK wraps — every endpoint, parameter, and response shape.
67
+
68
+
69
+ > **TIP:** Adding your own resources? The [`spree generate api_resource`](../../tutorial/api.md) generator scaffolds Admin API endpoints (model, serializers, controllers, specs) in one command, and the [extending guide](../extending.md) shows how to call custom endpoints from the SDK.
@@ -0,0 +1,126 @@
1
+ ---
2
+ title: "Resources"
3
+ description: "The full @spree/admin-sdk resource map — products, orders, customers, inventory, pricing, promotions, store configuration, and platform resources."
4
+ ---
5
+
6
+ Every Admin API resource is exposed as a property on the client (`client.orders`, `client.products`, …). Collection resources follow a consistent CRUD shape — `list`, `get`, `create`, `update`, `delete` — plus resource-specific actions. Nested resources take the **parent ID as the first argument**:
7
+
8
+ ```typescript
9
+ // Top-level
10
+ const order = await client.orders.get('order_xxx')
11
+
12
+ // Nested — parent ID first
13
+ const payments = await client.orders.payments.list('order_xxx')
14
+ await client.orders.payments.capture('order_xxx', 'payment_xxx')
15
+
16
+ // Nested create
17
+ await client.customers.addresses.create('cus_xxx', {
18
+ first_name: 'Jane',
19
+ last_name: 'Doe',
20
+ address1: '350 Fifth Avenue',
21
+ city: 'New York',
22
+ postal_code: '10118',
23
+ country_iso: 'US',
24
+ state_abbr: 'NY',
25
+ is_default_shipping: true,
26
+ })
27
+ ```
28
+
29
+ ## Catalog
30
+
31
+ | Client | Endpoints |
32
+ |---|---|
33
+ | `client.products` | CRUD, `clone`, and bulk operations (`bulkStatusUpdate`, `bulkAddToCategories` / `bulkRemoveFromCategories`, `bulkAddToChannels` / `bulkRemoveFromChannels`, `bulkAddTags` / `bulkRemoveTags`, `bulkDestroy`). Nested: `media`, `variants` (with their own `media`). |
34
+ | `client.variants` | Top-level variant search across products (`list`, `get`). |
35
+ | `client.optionTypes` | CRUD on option types and their values. |
36
+ | `client.categories` | List categories. |
37
+ | `client.tags` | Autocomplete tag names per taggable type. |
38
+ | `client.taxCategories` | CRUD on tax categories. |
39
+
40
+ ## Orders & fulfillment
41
+
42
+ | Client | Endpoints |
43
+ |---|---|
44
+ | `client.orders` | List, get, create, update, delete, `complete`, `cancel`, `approve`, `resume`, `resendConfirmation`. Nested: `items`, `payments` (incl. `capture` / `void`), `fulfillments` (incl. `fulfill` / `cancel` / `resume` / `split`), `refunds`, `giftCards`, `storeCredits`, `adjustments`. |
45
+
46
+ ## Customers
47
+
48
+ | Client | Endpoints |
49
+ |---|---|
50
+ | `client.customers` | CRUD plus bulk group operations (`bulkAddToGroups` / `bulkRemoveFromGroups`) and bulk tags. Nested: `addresses`, `creditCards`, `storeCredits`. |
51
+ | `client.customerGroups` | CRUD on customer groups. |
52
+
53
+ ## Pricing & promotions
54
+
55
+ | Client | Endpoints |
56
+ |---|---|
57
+ | `client.prices` | CRUD plus `bulkUpsert` / `bulkDestroy` for variant prices. |
58
+ | `client.priceLists` | CRUD, `activate` / `deactivate`, and price-list rule types. |
59
+ | `client.promotions` | CRUD. Nested: `actions`, `rules`, `couponCodes`. |
60
+ | `client.promotionActions` | Lookup of available action `types` and `calculators`. |
61
+ | `client.promotionRules` | Lookup of available rule `types`. |
62
+ | `client.giftCards` | CRUD on gift cards. |
63
+ | `client.giftCardBatches` | List, get, and create gift card batches. |
64
+ | `client.storeCreditCategories` | List and read store credit categories. |
65
+
66
+ ## Inventory
67
+
68
+ | Client | Endpoints |
69
+ |---|---|
70
+ | `client.stockLocations` | CRUD on stock locations. |
71
+ | `client.stockItems` | List, get, update, delete stock items. |
72
+ | `client.stockTransfers` | List, get, create, delete stock transfers. |
73
+
74
+ ## Sales channels
75
+
76
+ | Client | Endpoints |
77
+ |---|---|
78
+ | `client.channels` | CRUD plus `addProducts` / `removeProducts`. |
79
+ | `client.markets` | CRUD on markets. |
80
+
81
+ ## Store configuration
82
+
83
+ | Client | Endpoints |
84
+ |---|---|
85
+ | `client.store` | Store profile (`get`, `update`). |
86
+ | `client.paymentMethods` | CRUD plus `types` (available gateway types). |
87
+ | `client.countries` | List and read countries (for address dropdowns). |
88
+ | `client.customFieldDefinitions` | CRUD on [custom field](../../core-concepts/metafields.md) definitions. |
89
+ | `client.exports` | Create and track CSV exports (products, orders, customers, …). |
90
+ | `client.directUploads` | Pre-signed Active Storage uploads (used by media flows). |
91
+
92
+ ## Platform & access
93
+
94
+ | Client | Endpoints |
95
+ |---|---|
96
+ | `client.auth` | Login (email/password or identity provider), cookie-driven refresh, logout, invitation lookup/acceptance — see [Authentication](authentication.md). |
97
+ | `client.me` | Current admin user + permissions. |
98
+ | `client.adminUsers` | List, get, update, delete admin users. |
99
+ | `client.invitations` | Staff invitations — list, get, create, delete, `resend`. |
100
+ | `client.roles` | List and read roles. |
101
+ | `client.apiKeys` | CRUD plus `revoke` for API keys. |
102
+ | `client.allowedOrigins` | CRUD on CORS allowed origins. |
103
+ | `client.webhookEndpoints` | CRUD, `sendTest`, `enable` / `disable`. Nested: `deliveries` (list, get, `redeliver`). |
104
+ | `client.dashboard` | Sales analytics. |
105
+
106
+ ## Custom fields
107
+
108
+ Resources that support [custom fields](../../core-concepts/metafields.md) (products, variants, orders, customers, categories, option types) expose a `customFields` accessor taking the parent ID first:
109
+
110
+ ```typescript
111
+ await client.products.customFields.list('prod_xxx')
112
+ await client.products.customFields.create('prod_xxx', {
113
+ custom_field_definition_id: 'cfd_xxx',
114
+ value: 'limited-edition',
115
+ })
116
+ ```
117
+
118
+ The generic escape hatch covers any owner type:
119
+
120
+ ```typescript
121
+ await client.customFields('Spree::Product', 'prod_xxx').list()
122
+ ```
123
+
124
+ ## Adding your own resources
125
+
126
+ The resource map grows with your store. The [`spree generate api_resource`](../../tutorial/api.md) generator scaffolds new Admin API endpoints (model, serializers, controllers, routes, specs) in one command — then call them from the SDK with a [custom fetch or raw request](../extending.md), or generate a typed client for them.
@@ -3,6 +3,8 @@ title: Quickstart
3
3
  description: Install the Spree TypeScript SDK, configure your Store API client, and make your first calls to products, carts, checkout, and customer endpoints.
4
4
  ---
5
5
 
6
+ `@spree/sdk` is the customer-facing SDK — products, carts, checkout, and account flows against the Store API. For back-office integrations (managing products, orders, customers, stock), use the [Admin SDK](admin/quickstart.md).
7
+
6
8
  ## Installation
7
9
 
8
10
  ```bash
@@ -70,7 +72,6 @@ The SDK uses a resource builder pattern for nested resources:
70
72
  | `customer` | `orders` | `list` |
71
73
  | `customer` | `paymentSetupSessions` | `create`, `get`, `complete` |
72
74
  | `policies` | — | `list`, `get` |
73
- | `categories` | `products` | `list` |
74
75
  | `wishlists` | `items` | `create`, `update`, `delete` |
75
76
 
76
77
  ```typescript
@@ -79,7 +80,6 @@ await client.carts.items.create(cartId, params, options);
79
80
  await client.carts.payments.list(cartId, options);
80
81
  await client.carts.fulfillments.update(cartId, fulfillmentId, params, options);
81
82
  await client.customer.addresses.list({}, options);
82
- await client.categories.products.list(categoryId, params, options);
83
83
  await client.wishlists.items.create(wishlistId, params, options);
84
84
  ```
85
85
 
@@ -362,7 +362,7 @@ curl -X POST -H "X-Spree-API-Key: sk_YOUR_KEY" \
362
362
  http://localhost:3000/api/v3/admin/brands
363
363
  ```
364
364
 
365
- > **INFO:** Secret keys carry scopes (`read_brands`, `write_brands` style) and JWT admin users go through CanCanCan abilities — see [API authentication](../customization/api.md) for the full model.
365
+ > **INFO:** Secret keys carry scopes (`read_brands`, `write_brands` style) and JWT admin users go through CanCanCan abilities — see [API authentication](../customization/api.md) for the full model. From TypeScript, the [Admin SDK](../sdk/admin/quickstart.md) wraps the Admin API with typed clients for all built-in resources.
366
366
 
367
367
  ## Step 6: Add Brand to Product Responses
368
368
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spree/docs",
3
- "version": "0.1.88",
3
+ "version": "0.1.89",
4
4
  "description": "Spree Commerce developer documentation for AI agents and local reference",
5
5
  "type": "module",
6
6
  "license": "CC-BY-4.0",