@spree/docs 0.1.31 → 0.1.33
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.
- package/dist/api-reference/admin-api/authentication.md +161 -0
- package/dist/api-reference/admin-api/errors.md +277 -0
- package/dist/api-reference/admin-api/introduction.md +68 -0
- package/dist/api-reference/admin-api/querying.md +296 -0
- package/dist/api-reference/store.yaml +610 -528
- package/dist/developer/contributing/developing-spree.md +24 -11
- package/package.json +1 -1
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Querying"
|
|
3
|
+
sidebarTitle: "Querying"
|
|
4
|
+
description: "Filter, sort, paginate, and expand Admin API list responses"
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
The Admin API uses [Ransack](https://activerecord-hackery.github.io/ransack/) for filtering and sorting on collection endpoints. All filter conditions go through the `q` parameter; sorting and pagination are top-level params.
|
|
8
|
+
|
|
9
|
+
## Filtering
|
|
10
|
+
|
|
11
|
+
Pass filter conditions via `q`:
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
```typescript SDK
|
|
15
|
+
const orders = await client.orders.list({
|
|
16
|
+
status_eq: 'complete',
|
|
17
|
+
total_gteq: 100,
|
|
18
|
+
email_cont: '@example.com',
|
|
19
|
+
})
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
```bash cURL
|
|
23
|
+
curl -G 'https://store.example.com/api/v3/admin/orders' \
|
|
24
|
+
-H 'X-Spree-Api-Key: sk_xxx' \
|
|
25
|
+
--data-urlencode 'q[status_eq]=complete' \
|
|
26
|
+
--data-urlencode 'q[total_gteq]=100' \
|
|
27
|
+
--data-urlencode 'q[email_cont]=@example.com'
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
> **NOTE:** The SDK automatically wraps filter keys in `q[...]` and appends `[]` for array values — pass flat params.
|
|
32
|
+
|
|
33
|
+
### Common predicates
|
|
34
|
+
|
|
35
|
+
| Predicate | Description | SDK | cURL |
|
|
36
|
+
|---|---|---|---|
|
|
37
|
+
| `eq` | Equals | `status_eq: 'complete'` | `q[status_eq]=complete` |
|
|
38
|
+
| `not_eq` | Not equals | `status_not_eq: 'canceled'` | `q[status_not_eq]=canceled` |
|
|
39
|
+
| `cont` | Contains (case-insensitive) | `email_cont: '@acme'` | `q[email_cont]=@acme` |
|
|
40
|
+
| `start` | Starts with | `number_start: 'R10'` | `q[number_start]=R10` |
|
|
41
|
+
| `end` | Ends with | `slug_end: 'sale'` | `q[slug_end]=sale` |
|
|
42
|
+
| `lt` / `lteq` | Less than / less than or equal | `total_lteq: 50` | `q[total_lteq]=50` |
|
|
43
|
+
| `gt` / `gteq` | Greater than / greater than or equal | `total_gteq: 100` | `q[total_gteq]=100` |
|
|
44
|
+
| `in` | In a list | `status_in: ['complete', 'canceled']` | `q[status_in][]=complete&q[status_in][]=canceled` |
|
|
45
|
+
| `null` / `not_null` | Is null / not null | `completed_at_not_null: true` | `q[completed_at_not_null]=true` |
|
|
46
|
+
| `true` / `false` | Boolean | `accepts_email_marketing_true: 1` | `q[accepts_email_marketing_true]=1` |
|
|
47
|
+
|
|
48
|
+
### Prefixed IDs in filters
|
|
49
|
+
|
|
50
|
+
Resource ID filters accept Stripe-style prefixed IDs directly. The server decodes them before querying:
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
```typescript SDK
|
|
54
|
+
// All orders for a specific customer
|
|
55
|
+
const orders = await client.orders.list({
|
|
56
|
+
user_id_eq: 'cus_UkLWZg9DAJ',
|
|
57
|
+
})
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
```bash cURL
|
|
61
|
+
curl -G 'https://store.example.com/api/v3/admin/orders' \
|
|
62
|
+
-H 'X-Spree-Api-Key: sk_xxx' \
|
|
63
|
+
--data-urlencode 'q[user_id_eq]=cus_UkLWZg9DAJ'
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
The same applies to `_id_in`, `_id_not_eq`, and other ID predicates.
|
|
68
|
+
|
|
69
|
+
### Combining filters
|
|
70
|
+
|
|
71
|
+
Multiple filters combine with AND:
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
```typescript SDK
|
|
75
|
+
// Completed orders over $100 from the last 7 days
|
|
76
|
+
const orders = await client.orders.list({
|
|
77
|
+
status_eq: 'complete',
|
|
78
|
+
total_gteq: 100,
|
|
79
|
+
completed_at_gteq: new Date(Date.now() - 7 * 86_400_000).toISOString(),
|
|
80
|
+
})
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```bash cURL
|
|
84
|
+
curl -G 'https://store.example.com/api/v3/admin/orders' \
|
|
85
|
+
-H 'X-Spree-Api-Key: sk_xxx' \
|
|
86
|
+
--data-urlencode 'q[status_eq]=complete' \
|
|
87
|
+
--data-urlencode 'q[total_gteq]=100' \
|
|
88
|
+
--data-urlencode 'q[completed_at_gteq]=2026-04-22T00:00:00Z'
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
### Filtering by association
|
|
93
|
+
|
|
94
|
+
Use underscore notation to filter on associated model attributes:
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
```typescript SDK
|
|
98
|
+
// Customers tagged as "wholesale"
|
|
99
|
+
const customers = await client.customers.list({
|
|
100
|
+
tags_name_eq: 'wholesale',
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
// Products in a specific category
|
|
104
|
+
const products = await client.products.list({
|
|
105
|
+
taxons_id_eq: 'ctg_xxx',
|
|
106
|
+
})
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
```bash cURL
|
|
110
|
+
curl -G 'https://store.example.com/api/v3/admin/customers' \
|
|
111
|
+
-H 'X-Spree-Api-Key: sk_xxx' \
|
|
112
|
+
--data-urlencode 'q[tags_name_eq]=wholesale'
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
### Custom search scopes
|
|
117
|
+
|
|
118
|
+
Some resources expose convenience search scopes:
|
|
119
|
+
|
|
120
|
+
| Resource | Scope | Example |
|
|
121
|
+
|---|---|---|
|
|
122
|
+
| Customers | `search` | Full-text over email + first/last name |
|
|
123
|
+
| Customers | `with_min_total_spent` | Filter by lifetime spend |
|
|
124
|
+
| Orders | `multi_search` | Number + email full-text |
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
```typescript SDK
|
|
128
|
+
const customers = await client.customers.list({
|
|
129
|
+
search: 'jane',
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
const vipCustomers = await client.customers.list({
|
|
133
|
+
with_min_total_spent: 1000,
|
|
134
|
+
})
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```bash cURL
|
|
138
|
+
curl -G 'https://store.example.com/api/v3/admin/customers' \
|
|
139
|
+
-H 'X-Spree-Api-Key: sk_xxx' \
|
|
140
|
+
--data-urlencode 'q[search]=jane'
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
## Sorting
|
|
145
|
+
|
|
146
|
+
Use the top-level `sort` parameter on any list endpoint. Prefix with `-` for descending. Follows the [JSON:API sorting convention](https://jsonapi.org/format/#fetching-sorting).
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
```typescript SDK
|
|
150
|
+
// Most recent orders first
|
|
151
|
+
const orders = await client.orders.list({
|
|
152
|
+
sort: '-completed_at',
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
// Multiple sort keys (priority left to right)
|
|
156
|
+
const customers = await client.customers.list({
|
|
157
|
+
sort: '-total_spent,email',
|
|
158
|
+
})
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
```bash cURL
|
|
162
|
+
curl -G 'https://store.example.com/api/v3/admin/orders' \
|
|
163
|
+
-H 'X-Spree-Api-Key: sk_xxx' \
|
|
164
|
+
-d 'sort=-completed_at'
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
Sortable columns are limited to those whitelisted on the model (Ransack's `whitelisted_ransackable_attributes`). Sorting on a virtual column (e.g., a serializer-computed field like `display_total_spent`) is not supported.
|
|
169
|
+
|
|
170
|
+
## Pagination
|
|
171
|
+
|
|
172
|
+
All collection endpoints return paginated results. Control with `page` and `limit`:
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
```typescript SDK
|
|
176
|
+
const { data: orders, meta } = await client.orders.list({
|
|
177
|
+
page: 2,
|
|
178
|
+
limit: 50,
|
|
179
|
+
})
|
|
180
|
+
|
|
181
|
+
// meta.count, meta.pages, meta.previous, meta.next ...
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
```bash cURL
|
|
185
|
+
curl -G 'https://store.example.com/api/v3/admin/orders' \
|
|
186
|
+
-H 'X-Spree-Api-Key: sk_xxx' \
|
|
187
|
+
-d 'page=2' \
|
|
188
|
+
-d 'limit=50'
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
| Parameter | Default | Max | Description |
|
|
193
|
+
|---|---|---|---|
|
|
194
|
+
| `page` | `1` | — | Page number (1-indexed) |
|
|
195
|
+
| `limit` | `25` | `100` | Records per page |
|
|
196
|
+
|
|
197
|
+
### Pagination metadata
|
|
198
|
+
|
|
199
|
+
Responses include a `meta` object:
|
|
200
|
+
|
|
201
|
+
```json
|
|
202
|
+
{
|
|
203
|
+
"data": [...],
|
|
204
|
+
"meta": {
|
|
205
|
+
"page": 2,
|
|
206
|
+
"limit": 50,
|
|
207
|
+
"count": 327,
|
|
208
|
+
"pages": 7,
|
|
209
|
+
"from": 51,
|
|
210
|
+
"to": 100,
|
|
211
|
+
"in": 50,
|
|
212
|
+
"previous": 1,
|
|
213
|
+
"next": 3
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
| Field | Description |
|
|
219
|
+
|---|---|
|
|
220
|
+
| `page` | Current page number |
|
|
221
|
+
| `limit` | Records per page |
|
|
222
|
+
| `count` | Total number of matching records |
|
|
223
|
+
| `pages` | Total number of pages |
|
|
224
|
+
| `from` / `to` / `in` | Position range / count of this page |
|
|
225
|
+
| `previous` / `next` | Previous/next page number, or `null` |
|
|
226
|
+
|
|
227
|
+
## Expanding associations
|
|
228
|
+
|
|
229
|
+
Most admin endpoints return slim payloads by default — associations are returned as IDs. Use the `expand` parameter to include related resources inline:
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
```typescript SDK
|
|
233
|
+
const order = await client.orders.get('or_xxx', {
|
|
234
|
+
expand: ['items', 'fulfillments', 'payments', 'customer'],
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
// Nested expand
|
|
238
|
+
const customer = await client.customers.get('cus_xxx', {
|
|
239
|
+
expand: ['addresses', 'store_credits'],
|
|
240
|
+
})
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
```bash cURL
|
|
244
|
+
curl -G 'https://store.example.com/api/v3/admin/orders/or_xxx' \
|
|
245
|
+
-H 'X-Spree-Api-Key: sk_xxx' \
|
|
246
|
+
-d 'expand=items,fulfillments,payments,customer'
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
### Nested expand
|
|
251
|
+
|
|
252
|
+
Use dot notation up to 4 levels deep:
|
|
253
|
+
|
|
254
|
+
```typescript
|
|
255
|
+
const order = await client.orders.get('or_xxx', {
|
|
256
|
+
expand: ['items.variant.product', 'fulfillments.tracking'],
|
|
257
|
+
})
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
A nested expand implicitly includes its parent — `expand: ['items.variant']` returns both `items` and their `variant` data.
|
|
261
|
+
|
|
262
|
+
### What can I expand?
|
|
263
|
+
|
|
264
|
+
Each endpoint documents its supported expand keys in the OpenAPI reference. Common admin expansions:
|
|
265
|
+
|
|
266
|
+
| Resource | Common expands |
|
|
267
|
+
|---|---|
|
|
268
|
+
| Orders | `items`, `fulfillments`, `payments`, `customer`, `discounts`, `adjustments`, `billing_address`, `shipping_address` |
|
|
269
|
+
| Customers | `addresses`, `store_credits`, `orders` |
|
|
270
|
+
| Products | `variants`, `media`, `option_types`, `categories` |
|
|
271
|
+
|
|
272
|
+
## Field selection
|
|
273
|
+
|
|
274
|
+
Use the `fields` parameter to request only specific fields on a resource. Reduces payload size for bandwidth-sensitive integrations:
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
```typescript SDK
|
|
278
|
+
const orders = await client.orders.list({
|
|
279
|
+
fields: ['number', 'total', 'status', 'completed_at'],
|
|
280
|
+
})
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
```bash cURL
|
|
284
|
+
curl -G 'https://store.example.com/api/v3/admin/orders' \
|
|
285
|
+
-H 'X-Spree-Api-Key: sk_xxx' \
|
|
286
|
+
-d 'fields=number,total,status,completed_at'
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
Rules:
|
|
291
|
+
|
|
292
|
+
- `id` is always included
|
|
293
|
+
- Expanded associations return their full payload regardless of `fields`
|
|
294
|
+
- Field selection applies to the top-level resource only
|
|
295
|
+
|
|
296
|
+
> **NOTE:** TypeScript types in `@spree/admin-sdk` remain fully typed regardless of `fields`. At runtime, only the requested fields are present — the rest are `undefined`.
|