--- openapi: 3.0.3 info: title: Admin API contact: name: Spree Commerce url: https://spreecommerce.org email: hello@spreecommerce.org description: | Spree Admin API v3 - Administrative API for managing products, orders, and store settings. ## Authentication The Admin API requires a secret API key passed in the `x-spree-api-key` header. Secret API keys can be generated in the Spree admin dashboard. ## Response Format All responses are JSON. List endpoints return paginated responses with `data` and `meta` keys. Single resource endpoints return a flat JSON object. ## Resource IDs Every resource is identified by an opaque string ID (e.g. `prod_86Rf07xd4z`, `variant_k5nR8xLq`, `or_UkLWZg9DAJ`). Use these IDs everywhere — URL paths, request bodies, and Ransack filters all accept them directly. ## Error Handling Errors return a consistent format: ```json { "error": { "code": "validation_error", "message": "Validation failed", "details": { "name": ["can't be blank"] } } } ``` version: v3 paths: "/api/v3/admin/auth/login": post: summary: Login tags: - Authentication security: - api_key: [] description: | Authenticates an admin user and returns a short-lived JWT access token. The rotatable refresh token is set in an HttpOnly cookie — it is not included in the response body. Dispatches by the `provider` field to a strategy registered in `Spree.admin_authentication_strategies`. When `provider` is omitted it defaults to `email`, which uses the built-in email/password strategy. To plug in a third-party identity provider (Okta, Azure AD, Google Workspace SSO, a custom JWT issuer, SAML, etc.), register a `Spree::Authentication::Strategies::BaseStrategy` subclass under a provider key, then send `{ "provider": "", ... }` with the fields your strategy requires. The endpoint returns the same Spree-issued JWT regardless of which strategy authenticated the request. x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) // The refresh token is set as an HttpOnly cookie; only `token` and `user` come back in the body. const auth = await client.auth.login({ email: 'admin@example.com', password: 'password123', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string responses: '200': description: login successful content: application/json: example: token: eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VyX3R5cGUiOiJhZG1pbiIsImp0aSI6ImUyMzYxNTc5LWMxZDMtNDc0Yi1hM2E1LTcwNWMzYTZmMGUxYSIsImlzcyI6InNwcmVlIiwiYXVkIjoiYWRtaW5fYXBpIiwiZXhwIjoxNzgxMjg1MzI3fQ.5GaxxoaCeEEpGgum01ZV0z56ZpHDWaFSyX_KvEob3ws user: id: admin_UkLWZg9DAJ email: admin@example.com first_name: Lisandra last_name: Dare full_name: Lisandra Dare created_at: '2026-06-12T17:23:47.304Z' updated_at: '2026-06-12T17:23:47.304Z' roles: - id: role_UkLWZg9DAJ name: admin schema: "$ref": "#/components/schemas/AuthResponse" '401': description: invalid credentials content: application/json: example: error: code: authentication_failed message: Invalid email or password schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: oneOf: - title: EmailPasswordLogin description: Built-in email/password authentication (default when `provider` is omitted). type: object properties: provider: type: string enum: - email default: email email: type: string format: email example: admin@example.com password: type: string example: password123 required: - email - password - title: ProviderLogin description: | Provider-dispatched login. The `provider` key selects a registered strategy class; the remaining fields are forwarded to the strategy's `authenticate` method. Required fields depend on the registered strategy — consult its documentation. type: object properties: provider: type: string example: okta description: Registered provider key (anything other than `email`). not: enum: - email required: - provider additionalProperties: true "/api/v3/admin/auth/refresh": post: summary: Refresh token tags: - Authentication security: - api_key: [] description: | Exchanges the HttpOnly refresh-token cookie for a new access JWT and a rotated refresh token cookie. No request body or Authorization header is required — the cookie alone authenticates the call. x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) // Driven entirely by the HttpOnly refresh-token cookie + CSRF header (set by the SDK). const auth = await client.auth.refresh() parameters: - name: x-spree-api-key in: header required: true schema: type: string responses: '200': description: refresh successful content: application/json: example: token: eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VyX3R5cGUiOiJhZG1pbiIsImp0aSI6IjYxNTkwZmYyLWEwMTctNDUyZi05ZjQ3LTBhM2JhYWZlYWQ0YiIsImlzcyI6InNwcmVlIiwiYXVkIjoiYWRtaW5fYXBpIiwiZXhwIjoxNzgxMjg1MzI4fQ.l53NCGqm7_mD8L54Wq7AB86HGHqolGJEplh7Dg_QqJw user: id: admin_UkLWZg9DAJ email: admin@example.com first_name: Lavonda last_name: Bogan full_name: Lavonda Bogan created_at: '2026-06-12T17:23:48.682Z' updated_at: '2026-06-12T17:23:48.682Z' roles: - id: role_UkLWZg9DAJ name: admin schema: "$ref": "#/components/schemas/AuthResponse" '401': description: missing or invalid refresh-token cookie content: application/json: example: error: code: invalid_refresh_token message: Refresh token cookie missing schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v3/admin/auth/logout": post: summary: Logout tags: - Authentication security: - api_key: [] description: Revokes the refresh-token cookie, effectively logging the admin out. x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.auth.logout() parameters: - name: x-spree-api-key in: header required: true schema: type: string responses: '204': description: logout successful "/api/v3/admin/me": get: summary: Get current admin user and permissions tags: - Authentication security: - api_key: [] bearer_auth: [] description: Returns the current admin user profile and a serialized list of permissions (CanCanCan rules). The SPA uses these to drive UI permission checks. x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const me = await client.me.get() if (me.permissions.some((r) => r.allow && r.actions.includes('manage') && r.subjects.includes('Spree::Product'))) { // show "Create product" button } parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '200': description: current admin user and permissions content: application/json: example: user: id: admin_UkLWZg9DAJ email: loralee@bodeolson.name first_name: Thelma last_name: Cronin full_name: Thelma Cronin created_at: '2026-06-12T17:24:22.538Z' updated_at: '2026-06-12T17:24:22.538Z' roles: - id: role_UkLWZg9DAJ name: admin permissions: - allow: true actions: - manage subjects: - all has_conditions: false - allow: false actions: - cancel subjects: - Spree::Order has_conditions: false - allow: true actions: - cancel subjects: - Spree::Order has_conditions: true - allow: false actions: - destroy subjects: - Spree::Order has_conditions: false - allow: true actions: - destroy subjects: - Spree::Order has_conditions: true - allow: false actions: - edit - update subjects: - Spree::RefundReason has_conditions: true - allow: false actions: - edit - update subjects: - Spree::ReimbursementType has_conditions: true - allow: false actions: - update - destroy subjects: - Spree::Role has_conditions: true schema: "$ref": "#/components/schemas/MeResponse" '401': description: unauthorized content: application/json: example: error: code: authentication_required message: Authentication required schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v3/admin/allowed_origins": get: summary: List allowed origins tags: - Allowed Origins security: - api_key: [] bearer_auth: [] description: |- Returns the CORS allowlist for the current store. Each entry is a bare `scheme://host[:port]` permitted to call the admin API from a browser. Backs the `Rack::Cors` allowlist and the CSRF boundary of the admin cookie session (see `docs/plans/5.5-admin-auth-cookie-refresh.md`). **Required scope:** `read_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: origins } = await client.allowedOrigins.list() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: page in: query required: false description: Page number schema: type: integer - name: limit in: query required: false description: Number of records per page schema: type: integer - name: q[origin_cont] in: query required: false description: Filter by origin (contains) schema: type: string - name: sort in: query required: false description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include. id is always included. schema: type: string responses: '200': description: allowed origins found content: application/json: example: data: - id: ao_UkLWZg9DAJ origin: https://shop.example.com created_at: '2026-06-12T17:23:42.410Z' updated_at: '2026-06-12T17:23:42.410Z' meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: schema: type: object properties: data: type: array items: "$ref": "#/components/schemas/AllowedOrigin" meta: "$ref": "#/components/schemas/PaginationMeta" required: - data - meta '401': description: unauthorized content: application/json: example: error: code: authentication_required message: Authentication required schema: "$ref": "#/components/schemas/ErrorResponse" post: summary: Create an allowed origin tags: - Allowed Origins security: - api_key: [] bearer_auth: [] description: |- Adds an origin to the admin CORS allowlist. The value must be a bare `scheme://host[:port]` (no path, query, or fragment) and use `http` or `https`. **Required scope:** `write_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const origin = await client.allowedOrigins.create({ origin: 'https://admin.example.com', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '201': description: allowed origin created content: application/json: example: id: ao_gbHJdmfrXB origin: https://admin.example.com created_at: '2026-06-12T17:23:43.075Z' updated_at: '2026-06-12T17:23:43.075Z' schema: "$ref": "#/components/schemas/AllowedOrigin" '422': description: validation error content: application/json: example: error: code: validation_error message: Origin is invalid details: origin: - is invalid schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: origin: type: string example: https://admin.example.com required: - origin "/api/v3/admin/allowed_origins/{id}": parameters: - name: id in: path required: true description: Allowed origin ID schema: type: string get: summary: Get an allowed origin tags: - Allowed Origins security: - api_key: [] bearer_auth: [] description: |- Returns a single allowed origin by prefixed ID. **Required scope:** `read_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const origin = await client.allowedOrigins.get('ao_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include. id is always included. schema: type: string responses: '200': description: allowed origin found content: application/json: example: id: ao_UkLWZg9DAJ origin: https://shop.example.com created_at: '2026-06-12T17:23:43.396Z' updated_at: '2026-06-12T17:23:43.396Z' schema: "$ref": "#/components/schemas/AllowedOrigin" '404': description: allowed origin not found content: application/json: example: error: code: record_not_found message: Allowed origin not found schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update an allowed origin tags: - Allowed Origins security: - api_key: [] bearer_auth: [] description: |- Updates an existing allowed origin. **Required scope:** `write_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const origin = await client.allowedOrigins.update('ao_xxx', { origin: 'https://www.example.com', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '200': description: allowed origin updated content: application/json: example: id: ao_UkLWZg9DAJ origin: https://www.example.com created_at: '2026-06-12T17:23:44.064Z' updated_at: '2026-06-12T17:23:44.366Z' schema: "$ref": "#/components/schemas/AllowedOrigin" '422': description: validation error content: application/json: example: error: code: validation_error message: Origin must be an origin (scheme and host) without path, query, or fragment details: origin: - must be an origin (scheme and host) without path, query, or fragment schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: origin: type: string delete: summary: Delete an allowed origin tags: - Allowed Origins security: - api_key: [] bearer_auth: [] description: |- Removes an origin from the admin CORS allowlist. After deletion the admin SPA running at that origin will no longer be able to call the admin API from a browser. **Required scope:** `write_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.allowedOrigins.delete('ao_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '204': description: allowed origin deleted "/api/v3/admin/api_keys": get: summary: List API keys tags: - API Keys security: - api_key: [] bearer_auth: [] description: |- Returns publishable and secret API keys for the current store. Secret keys are listed by `token_prefix` only — the plaintext token is delivered exactly once on create. **Required scope:** `read_api_keys` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: keys } = await client.apiKeys.list() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: API keys found content: application/json: example: data: - id: key_UkLWZg9DAJ name: Storefront key key_type: publishable token_prefix: scopes: [] created_at: '2026-06-12T17:23:45.015Z' updated_at: '2026-06-12T17:23:45.015Z' revoked_at: last_used_at: plaintext_token: pk_5AskmHCv2omYyoBr3mehREcX created_by_email: - id: key_gbHJdmfrXB name: Backend integration key_type: secret token_prefix: sk_qBGxwGooh scopes: - write_all created_at: '2026-06-12T17:23:45.016Z' updated_at: '2026-06-12T17:23:45.016Z' revoked_at: last_used_at: plaintext_token: created_by_email: - id: key_EfhxLZ9ck8 name: minima key_type: secret token_prefix: sk_2bVt6n2wq scopes: - write_all created_at: '2026-06-12T17:23:45.017Z' updated_at: '2026-06-12T17:23:45.017Z' revoked_at: last_used_at: plaintext_token: created_by_email: meta: page: 1 limit: 25 count: 3 pages: 1 from: 1 to: 3 in: 3 previous: next: post: summary: Create an API key tags: - API Keys security: - api_key: [] bearer_auth: [] description: |- Creates a publishable or secret API key. The plaintext token is included in the response **once** for secret keys; publishable keys expose their token on every read since they are intended for client-side use. **Required scope:** `write_api_keys` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const key = await client.apiKeys.create({ name: 'Backend integration', key_type: 'secret', scopes: ['read_orders', 'write_orders'] }) // `key.plaintext_token` is available only on this response. parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '201': description: secret key created — plaintext token returned once content: application/json: example: id: key_VqXmZF31wY name: CI key key_type: secret token_prefix: sk_vGdftBeFe scopes: - read_orders created_at: '2026-06-12T17:23:45.625Z' updated_at: '2026-06-12T17:23:45.625Z' revoked_at: last_used_at: plaintext_token: sk_vGdftBeFecVvHg1towF93knP created_by_email: dirk_morar@ohara.info '422': description: validation error content: application/json: example: error: code: validation_error message: Name can't be blank and Scopes can't be blank details: name: - can't be blank scopes: - can't be blank requestBody: content: application/json: schema: type: object required: - name - key_type properties: name: type: string example: Backend integration key_type: type: string enum: - publishable - secret scopes: type: array items: type: string example: - read_orders - write_orders "/api/v3/admin/api_keys/{id}": get: summary: Show an API key tags: - API Keys security: - api_key: [] bearer_auth: [] description: "**Required scope:** `read_api_keys` (for API-key authentication)." x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const key = await client.apiKeys.get('key_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '200': description: API key found content: application/json: example: id: key_UkLWZg9DAJ name: Storefront key key_type: publishable token_prefix: scopes: [] created_at: '2026-06-12T17:23:45.944Z' updated_at: '2026-06-12T17:23:45.944Z' revoked_at: last_used_at: plaintext_token: pk_bZ5pTDmsuFozzLiikk62bCgQ created_by_email: delete: summary: Delete an API key tags: - API Keys security: - api_key: [] bearer_auth: [] description: "**Required scope:** `write_api_keys` (for API-key authentication)." x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.apiKeys.delete('key_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '204': description: API key deleted "/api/v3/admin/api_keys/{id}/revoke": patch: summary: Revoke an API key tags: - API Keys security: - api_key: [] bearer_auth: [] description: |- Marks the key revoked. Future requests using its token will fail; the row is preserved for audit. **Required scope:** `write_api_keys` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const key = await client.apiKeys.revoke('key_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '200': description: API key revoked content: application/json: example: id: key_gbHJdmfrXB name: Backend integration key_type: secret token_prefix: sk_PVNjbM3kV scopes: - write_all created_at: '2026-06-12T17:23:46.589Z' updated_at: '2026-06-12T17:23:47.008Z' revoked_at: '2026-06-12T17:23:47.006Z' last_used_at: plaintext_token: created_by_email: "/api/v3/admin/channels": get: summary: List channels tags: - Channels security: - api_key: [] bearer_auth: [] description: |- Returns the channels configured for the current store. **Required scope:** `read_settings` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: page in: query required: false schema: type: integer - name: limit in: query required: false schema: type: integer responses: '200': description: channels found content: application/json: example: data: - id: ch_UkLWZg9DAJ name: Online Store code: online active: true default: true preferred_order_routing_strategy: created_at: '2026-06-12T17:23:41.100Z' updated_at: '2026-06-12T17:23:41.100Z' - id: ch_gbHJdmfrXB name: Wholesale code: wholesale active: true default: false preferred_order_routing_strategy: created_at: '2026-06-12T17:23:49.367Z' updated_at: '2026-06-12T17:23:49.367Z' meta: page: 1 limit: 25 count: 2 pages: 1 from: 1 to: 2 in: 2 previous: next: schema: type: object properties: data: type: array items: "$ref": "#/components/schemas/Channel" meta: "$ref": "#/components/schemas/PaginationMeta" required: - data - meta post: summary: Create a channel tags: - Channels security: - api_key: [] bearer_auth: [] description: |- Creates a new channel on the current store. `code` is normalized to a URL-safe slug (`Point of Sale` → `point-of-sale`); when omitted it's derived from `name`. **Required scope:** `write_settings` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '201': description: channel created content: application/json: example: id: ch_EfhxLZ9ck8 name: Marketplace code: marketplace active: true default: false preferred_order_routing_strategy: created_at: '2026-06-12T17:23:50.024Z' updated_at: '2026-06-12T17:23:50.024Z' requestBody: content: application/json: schema: type: object required: - name properties: name: type: string example: Point of Sale code: type: string example: pos description: Slug — auto-derived from `name` when blank. active: type: boolean default: true "/api/v3/admin/channels/{id}": parameters: - name: id in: path required: true schema: type: string get: summary: Get a channel tags: - Channels security: - api_key: [] bearer_auth: [] description: "**Required scope:** `read_settings` (for API-key authentication)." parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: channel found content: application/json: example: id: ch_gbHJdmfrXB name: Wholesale code: wholesale active: true default: false preferred_order_routing_strategy: created_at: '2026-06-12T17:23:50.035Z' updated_at: '2026-06-12T17:23:50.035Z' patch: summary: Update a channel tags: - Channels security: - api_key: [] bearer_auth: [] description: "**Required scope:** `write_settings` (for API-key authentication)." parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: channel updated content: application/json: example: id: ch_gbHJdmfrXB name: Wholesale (Updated) code: wholesale active: true default: false preferred_order_routing_strategy: created_at: '2026-06-12T17:23:50.514Z' updated_at: '2026-06-12T17:23:50.908Z' requestBody: content: application/json: schema: type: object properties: name: type: string code: type: string active: type: boolean delete: summary: Delete a channel tags: - Channels security: - api_key: [] bearer_auth: [] description: "**Required scope:** `write_settings` (for API-key authentication)." parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '204': description: channel deleted "/api/v3/admin/channels/{id}/add_products": parameters: - name: id in: path required: true schema: type: string post: summary: Publish products on a channel tags: - Channels security: - api_key: [] bearer_auth: [] description: |- Publishes the listed products on this channel. Idempotent — re-publishing an already-published product updates its publication window. Products from sibling stores are silently dropped. **Required scope:** `write_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: products published content: application/json: example: product_count: 1 schema: type: object properties: product_count: type: integer requestBody: content: application/json: schema: type: object required: - product_ids properties: product_ids: type: array items: type: string published_at: type: string format: date-time nullable: true description: When the publications go live. `null` means immediately. unpublished_at: type: string format: date-time nullable: true description: When the publications come down. `null` means never. "/api/v3/admin/channels/{id}/remove_products": parameters: - name: id in: path required: true schema: type: string post: summary: Unpublish products from a channel tags: - Channels security: - api_key: [] bearer_auth: [] description: |- Unpublishes the listed products from this channel. **Required scope:** `write_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: products unpublished content: application/json: example: product_count: 1 schema: type: object properties: product_count: type: integer requestBody: content: application/json: schema: type: object required: - product_ids properties: product_ids: type: array items: type: string "/api/v3/admin/custom_field_definitions": get: summary: List custom field definitions tags: - Custom Fields security: - api_key: [] bearer_auth: [] description: |- Returns all defined custom fields. Filter by `?q[resource_type_eq]=Spree::Product` to narrow to one parent type. **Required scope:** `read_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: definitions } = await client.customFieldDefinitions.list({ q: { resource_type_eq: 'Spree::Product' }, }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand. Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., key,label,field_type). id is always included. schema: type: string responses: '200': description: definitions returned content: application/json: example: data: - id: cfdef_UkLWZg9DAJ namespace: specs key: fabric label: Title field_type: short_text resource_type: Spree::Product storefront_visible: true created_at: '2026-06-12T17:23:52.898Z' updated_at: '2026-06-12T17:23:52.898Z' - id: cfdef_gbHJdmfrXB namespace: custom key: order_notes label: Order Notes field_type: short_text resource_type: Spree::Order storefront_visible: true created_at: '2026-06-12T17:23:52.900Z' updated_at: '2026-06-12T17:23:52.900Z' meta: page: 1 limit: 25 count: 2 pages: 1 from: 1 to: 2 in: 2 previous: next: post: summary: Create a custom field definition tags: - Custom Fields security: - api_key: [] bearer_auth: [] description: "**Required scope:** `write_settings` (for API-key authentication)." x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const definition = await client.customFieldDefinitions.create({ namespace: 'specs', key: 'origin', label: 'Country of Origin', field_type: 'short_text', resource_type: 'Spree::Product', storefront_visible: true, }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '201': description: definition created content: application/json: example: id: cfdef_EfhxLZ9ck8 namespace: specs key: origin label: Country of Origin field_type: short_text resource_type: Spree::Product storefront_visible: true created_at: '2026-06-12T17:23:53.559Z' updated_at: '2026-06-12T17:23:53.559Z' requestBody: content: application/json: schema: type: object required: - key - field_type - resource_type properties: namespace: type: string description: Defaults to `custom` key: type: string label: type: string description: Human-readable name; defaults to titleized `key` field_type: type: string description: Custom field type identifier (one of the registered field-type class names). resource_type: type: string description: Owner class, e.g. `Spree::Product` storefront_visible: type: boolean description: 'When false, definition is admin-only (was `display_on: back_end`)' "/api/v3/admin/custom_field_definitions/{id}": get: summary: Show a custom field definition tags: - Custom Fields security: - api_key: [] bearer_auth: [] description: "**Required scope:** `read_settings` (for API-key authentication)." parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand. Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., key,label,field_type). id is always included. schema: type: string responses: '200': description: definition found content: application/json: example: id: cfdef_UkLWZg9DAJ namespace: specs key: fabric label: Title field_type: short_text resource_type: Spree::Product storefront_visible: true created_at: '2026-06-12T17:23:53.566Z' updated_at: '2026-06-12T17:23:53.566Z' patch: summary: Update a custom field definition tags: - Custom Fields security: - api_key: [] bearer_auth: [] description: "**Required scope:** `write_settings` (for API-key authentication)." parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '200': description: definition updated content: application/json: example: id: cfdef_UkLWZg9DAJ namespace: specs key: fabric label: Fabric Composition field_type: short_text resource_type: Spree::Product storefront_visible: false created_at: '2026-06-12T17:23:53.886Z' updated_at: '2026-06-12T17:23:54.207Z' requestBody: content: application/json: schema: type: object properties: label: type: string storefront_visible: type: boolean delete: summary: Delete a custom field definition tags: - Custom Fields security: - api_key: [] bearer_auth: [] description: |- Deletes the definition and cascades to all custom field values referencing it. **Required scope:** `write_settings` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '204': description: definition deleted "/api/v3/admin/customer_groups": get: summary: List customer groups tags: - Customer Groups security: - api_key: [] bearer_auth: [] description: |- Returns the customer groups configured for the current store. Groups segment customers for targeted promotions (see the `customer_group` promotion rule) and reporting. The list endpoint never embeds the member list — fetch a single group with `?expand=customers` if you need them inline, or query `/admin/customers?customer_group_id_in=…` for paginated membership. **Required scope:** `read_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: groups } = await client.customerGroups.list({ page: 1, limit: 25 }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: page in: query required: false description: Page number schema: type: integer - name: limit in: query required: false description: Number of records per page schema: type: integer - name: q[name_cont] in: query required: false description: Filter by name (contains) schema: type: string - name: sort in: query required: false description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include. id is always included. schema: type: string responses: '200': description: customer groups found content: application/json: example: data: - id: cg_UkLWZg9DAJ name: VIPs description: Top spenders customers_count: 0 created_at: '2026-06-12T17:23:54.579Z' updated_at: '2026-06-12T17:23:54.579Z' - id: cg_gbHJdmfrXB name: Wholesale description: customers_count: 0 created_at: '2026-06-12T17:23:54.580Z' updated_at: '2026-06-12T17:23:54.580Z' meta: page: 1 limit: 25 count: 2 pages: 1 from: 1 to: 2 in: 2 previous: next: schema: type: object properties: data: type: array items: "$ref": "#/components/schemas/CustomerGroup" meta: "$ref": "#/components/schemas/PaginationMeta" required: - data - meta '401': description: unauthorized content: application/json: example: error: code: authentication_required message: Authentication required schema: "$ref": "#/components/schemas/ErrorResponse" post: summary: Create a customer group tags: - Customer Groups security: - api_key: [] bearer_auth: [] description: |- Creates a customer group in the current store. `customer_ids` is optional; when present, customers are attached at create time. Pass prefixed IDs (e.g. `cus_…`) — the server decodes them automatically. **Required scope:** `write_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const group = await client.customerGroups.create({ name: 'VIP customers', description: 'Top spenders, eligible for early access', customer_ids: ['cus_UkLWZg9DAJ', 'cus_QrLWXg9CAJ'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '201': description: customer group created content: application/json: example: id: cg_EfhxLZ9ck8 name: Wholesale 2 description: B2B accounts customers_count: 1 created_at: '2026-06-12T17:23:55.564Z' updated_at: '2026-06-12T17:23:55.564Z' schema: "$ref": "#/components/schemas/CustomerGroup" '422': description: validation error content: application/json: example: error: code: validation_error message: Name can't be blank details: name: - can't be blank schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object required: - name properties: name: type: string example: Wholesale description: type: string example: B2B accounts nullable: true customer_ids: type: array items: type: string example: - cus_UkLWZg9DAJ "/api/v3/admin/customer_groups/{id}": parameters: - name: id in: path required: true description: Customer group prefixed ID schema: type: string get: summary: Get a customer group tags: - Customer Groups security: - api_key: [] bearer_auth: [] description: |- Returns a single customer group. Pass `?expand=customers` to embed the full member list inline (recommended only for single-record reads — embed cost scales with membership size). **Required scope:** `read_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) // Pass `expand: ['customers']` to embed the group's customers in the response // — omit it for the much smaller index-payload shape. const group = await client.customerGroups.get('cg_UkLWZg9DAJ', { expand: ['customers'] }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: expand in: query required: false description: 'Comma-separated associations to embed. Supported: `customers`.' schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include. id is always included. schema: type: string responses: '200': description: customer group with embedded customers content: application/json: example: id: cg_UkLWZg9DAJ name: VIPs description: Top spenders customers_count: 1 created_at: '2026-06-12T17:23:56.255Z' updated_at: '2026-06-12T17:23:56.255Z' customers: - id: cus_UkLWZg9DAJ email: edra@mitchell.biz first_name: Karly last_name: Labadie phone: accepts_email_marketing: false full_name: Karly Labadie available_store_credit_total: '0' display_available_store_credit_total: "$0.00" login: edra@mitchell.biz metadata: {} last_sign_in_at: current_sign_in_at: created_at: '2026-06-12T17:23:56.566Z' updated_at: '2026-06-12T17:23:56.566Z' sign_in_count: 0 failed_attempts: 0 last_sign_in_ip: current_sign_in_ip: tags: [] internal_note_html: default_billing_address_id: default_shipping_address_id: orders_count: 0 total_spent: '0.0' display_total_spent: "$0.00" last_order_completed_at: schema: "$ref": "#/components/schemas/CustomerGroup" '404': description: customer group not found content: application/json: example: error: code: record_not_found message: Customer group not found schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update a customer group tags: - Customer Groups security: - api_key: [] bearer_auth: [] description: |- Updates name, description, or membership. `customer_ids` is a full-set replacement — the server reconciles the membership to match the array, adding new IDs and removing ones not present. Send `customer_ids: []` to clear all members. **Required scope:** `write_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) // `customer_ids` is a full-set update — the model reconciles the membership // to match the array (adds new IDs, removes ones not present). const group = await client.customerGroups.update('cg_UkLWZg9DAJ', { name: 'VIP customers (Q1)', customer_ids: ['cus_UkLWZg9DAJ'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: customer group updated content: application/json: example: id: cg_UkLWZg9DAJ name: VIP customers (Q1) description: Top spenders customers_count: 0 created_at: '2026-06-12T17:23:57.311Z' updated_at: '2026-06-12T17:23:57.647Z' schema: "$ref": "#/components/schemas/CustomerGroup" '422': description: validation error content: application/json: example: error: code: validation_error message: Name can't be blank details: name: - can't be blank schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: name: type: string example: VIP customers (Q1) description: type: string example: Updated description nullable: true customer_ids: type: array items: type: string example: - cus_UkLWZg9DAJ delete: summary: Delete a customer group tags: - Customer Groups security: - api_key: [] bearer_auth: [] description: |- Soft-deletes the group. Member users are not deleted; their `customer_group_users` rows are dropped. **Required scope:** `write_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.customerGroups.delete('cg_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '204': description: customer group deleted "/api/v3/admin/customers/{customer_id}/addresses": get: summary: List customer addresses tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Returns the customer's saved addresses. **Required scope:** `read_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: addresses } = await client.customers.addresses.list('cus_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: customer_id in: path required: true schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., country, state). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., first_name,last_name,address1,city). id is always included. schema: type: string responses: '200': description: addresses found content: application/json: example: data: - id: addr_UkLWZg9DAJ first_name: John last_name: Doe full_name: John Doe address1: 1 Lovely Street address2: Northwest postal_code: '10118' city: New York phone: 555-555-0199 company: Company country_name: United States of America country_iso: US state_text: NY state_abbr: NY quick_checkout: false is_default_billing: false is_default_shipping: false state_name: New York label: metadata: {} created_at: '2026-06-12T17:23:58.540Z' updated_at: '2026-06-12T17:23:58.540Z' customer_id: cus_UkLWZg9DAJ meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: post: summary: Create a customer address tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Adds a new address to the customer's address book. Pass `is_default_billing: true` or `is_default_shipping: true` to set as the default — the previous default loses its flag in the same transaction. **Required scope:** `write_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const address = await client.customers.addresses.create('cus_UkLWZg9DAJ', { first_name: 'Jane', last_name: 'Doe', address1: '350 Fifth Avenue', city: 'New York', postal_code: '10118', country_iso: 'US', state_abbr: 'NY', phone: '+1 212 555 1234', label: 'Office', is_default_shipping: true, }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: customer_id in: path required: true schema: type: string responses: '201': description: address created content: application/json: example: id: addr_gbHJdmfrXB first_name: Jane last_name: Doe full_name: Jane Doe address1: 350 Fifth Avenue address2: postal_code: '10118' city: New York phone: "+12125551234" company: country_name: United States of America country_iso: US state_text: NY state_abbr: NY quick_checkout: false is_default_billing: false is_default_shipping: false state_name: New York label: Office metadata: {} created_at: '2026-06-12T17:23:59.952Z' updated_at: '2026-06-12T17:23:59.952Z' customer_id: cus_UkLWZg9DAJ requestBody: content: application/json: schema: type: object properties: first_name: type: string last_name: type: string address1: type: string address2: type: string city: type: string postal_code: type: string country_iso: type: string description: ISO-2 country code (e.g. US) state_abbr: type: string description: State/province abbreviation (e.g. NY) phone: type: string company: type: string label: type: string is_default_billing: type: boolean is_default_shipping: type: boolean "/api/v3/admin/customers/{customer_id}/addresses/{id}": patch: summary: Update a customer address tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Updates a customer address. **Required scope:** `write_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const address = await client.customers.addresses.update( 'cus_UkLWZg9DAJ', 'addr_UkLWZg9DAJ', { city: 'Manhattan' }, ) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: customer_id in: path required: true schema: type: string - name: id in: path required: true schema: type: string responses: '200': description: address updated content: application/json: example: id: addr_UkLWZg9DAJ first_name: John last_name: Doe full_name: John Doe address1: 3 Lovely Street address2: Northwest postal_code: '10118' city: Manhattan phone: 555-555-0199 company: Company country_name: United States of America country_iso: US state_text: NY state_abbr: NY quick_checkout: false is_default_billing: false is_default_shipping: false state_name: New York label: metadata: {} created_at: '2026-06-12T17:24:00.227Z' updated_at: '2026-06-12T17:24:00.777Z' customer_id: cus_UkLWZg9DAJ requestBody: content: application/json: schema: type: object properties: city: type: string is_default_billing: type: boolean is_default_shipping: type: boolean delete: summary: Delete a customer address tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Deletes the address. If it was a default, the customer loses that default (no auto-promotion). **Required scope:** `write_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.customers.addresses.delete('cus_UkLWZg9DAJ', 'addr_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: customer_id in: path required: true schema: type: string - name: id in: path required: true schema: type: string responses: '204': description: address deleted "/api/v3/admin/customers/{customer_id}/credit_cards": get: summary: List customer credit cards tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Returns the customer's saved credit cards. Useful for off-session admin charges via `POST /admin/orders/:id/payments { source_id }`. **Required scope:** `read_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: cards } = await client.customers.creditCards.list('cus_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: customer_id in: path required: true schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., payment_method). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., brand,last4,month,year). id is always included. schema: type: string responses: '200': description: credit cards found content: application/json: example: data: - id: card_UkLWZg9DAJ brand: visa last4: '1111' month: 12 year: 2027 name: Spree Commerce default: false gateway_payment_profile_id: customer_id: cus_UkLWZg9DAJ payment_method_id: pm_UkLWZg9DAJ metadata: {} created_at: '2026-06-12T17:24:01.924Z' updated_at: '2026-06-12T17:24:01.924Z' meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: "/api/v3/admin/customers/{customer_id}/credit_cards/{id}": get: summary: Show a customer credit card tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Returns a saved credit card by ID. **Required scope:** `read_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const card = await client.customers.creditCards.get('cus_UkLWZg9DAJ', 'cc_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: customer_id in: path required: true schema: type: string - name: id in: path required: true schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., payment_method). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., brand,last4,month,year). id is always included. schema: type: string responses: '200': description: credit card found content: application/json: example: id: card_UkLWZg9DAJ brand: visa last4: '1111' month: 12 year: 2027 name: Spree Commerce default: false gateway_payment_profile_id: customer_id: cus_UkLWZg9DAJ payment_method_id: pm_UkLWZg9DAJ metadata: {} created_at: '2026-06-12T17:24:02.498Z' updated_at: '2026-06-12T17:24:02.498Z' delete: summary: Delete a customer credit card tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Deletes a saved credit card. **Required scope:** `write_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.customers.creditCards.delete('cus_UkLWZg9DAJ', 'cc_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: customer_id in: path required: true schema: type: string - name: id in: path required: true schema: type: string responses: '204': description: credit card deleted "/api/v3/admin/customers/{customer_id}/store_credits": get: summary: List customer store credits tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Returns store credits issued to the customer. **Required scope:** `read_store_credits` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: storeCredits } = await client.customers.storeCredits.list('cus_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: customer_id in: path required: true schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., category, store, created_by). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., amount,amount_used,memo,currency). id is always included. schema: type: string responses: '200': description: store credits found content: application/json: example: data: - id: credit_UkLWZg9DAJ amount: '50.0' amount_used: '0.0' amount_remaining: '50.0' display_amount: "$50.00" display_amount_used: "$0.00" display_amount_remaining: "$50.00" currency: USD memo: metadata: {} created_at: '2026-06-12T17:24:03.896Z' updated_at: '2026-06-12T17:24:03.896Z' customer_id: cus_UkLWZg9DAJ created_by_id: admin_UkLWZg9DAJ category_id: sccat_UkLWZg9DAJ category_name: Exchange meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: post: summary: Issue a store credit to a customer tags: - Customers security: - api_key: [] bearer_auth: [] description: |- `created_by` is set automatically from the authenticated admin. **Required scope:** `write_store_credits` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const credit = await client.customers.storeCredits.create('cus_UkLWZg9DAJ', { amount: 25.00, currency: 'USD', category_id: 'cat_UkLWZg9DAJ', memo: 'Goodwill credit', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: customer_id in: path required: true schema: type: string responses: '201': description: store credit created content: application/json: example: id: credit_gbHJdmfrXB amount: '25.0' amount_used: '0.0' amount_remaining: '25.0' display_amount: "$25.00" display_amount_used: "$0.00" display_amount_remaining: "$25.00" currency: USD memo: Goodwill metadata: {} created_at: '2026-06-12T17:24:05.013Z' updated_at: '2026-06-12T17:24:05.013Z' customer_id: cus_UkLWZg9DAJ created_by_id: admin_gbHJdmfrXB category_id: sccat_UkLWZg9DAJ category_name: Exchange requestBody: content: application/json: schema: type: object required: - amount - currency - category_id properties: amount: type: number example: 50.0 currency: type: string example: USD category_id: type: string description: StoreCreditCategory ID memo: type: string "/api/v3/admin/customers/{customer_id}/store_credits/{id}": patch: summary: Update a store credit tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Update memo / category / amount. The amount can only be changed if `amount_used == 0`. **Required scope:** `write_store_credits` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const credit = await client.customers.storeCredits.update( 'cus_UkLWZg9DAJ', 'sc_UkLWZg9DAJ', { memo: 'Reissued for damaged shipment' }, ) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: customer_id in: path required: true schema: type: string - name: id in: path required: true schema: type: string responses: '200': description: store credit updated content: application/json: example: id: credit_UkLWZg9DAJ amount: '50.0' amount_used: '0.0' amount_remaining: '50.0' display_amount: "$50.00" display_amount_used: "$0.00" display_amount_remaining: "$50.00" currency: USD memo: Updated metadata: {} created_at: '2026-06-12T17:24:05.556Z' updated_at: '2026-06-12T17:24:05.841Z' customer_id: cus_UkLWZg9DAJ created_by_id: admin_UkLWZg9DAJ category_id: sccat_UkLWZg9DAJ category_name: Exchange requestBody: content: application/json: schema: type: object properties: amount: type: number category_id: type: string memo: type: string delete: summary: Delete a store credit tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Deletes an unused store credit (amount_used == 0). Returns 422 otherwise. **Required scope:** `write_store_credits` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.customers.storeCredits.delete('cus_UkLWZg9DAJ', 'sc_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: customer_id in: path required: true schema: type: string - name: id in: path required: true schema: type: string responses: '204': description: store credit deleted "/api/v3/admin/customers": get: summary: List customers tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Returns a paginated list of customers. Supports Ransack search/filters. **Required scope:** `read_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: customers } = await client.customers.list({ search: 'jane', sort: '-created_at', limit: 25, }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: page in: query required: false schema: type: integer - name: limit in: query required: false schema: type: integer - name: q[search] in: query required: false description: Email + name full-text-ish search schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., addresses, store_credits). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., email,first_name,last_name). id is always included. schema: type: string responses: '200': description: customers found content: application/json: example: data: - id: cus_UkLWZg9DAJ email: jane@example.com first_name: Jane last_name: Doe phone: accepts_email_marketing: false full_name: Jane Doe available_store_credit_total: '0' display_available_store_credit_total: "$0.00" login: jane@example.com metadata: {} last_sign_in_at: current_sign_in_at: created_at: '2026-06-12T17:24:06.985Z' updated_at: '2026-06-12T17:24:06.985Z' sign_in_count: 0 failed_attempts: 0 last_sign_in_ip: current_sign_in_ip: tags: [] internal_note_html: default_billing_address_id: default_shipping_address_id: orders_count: 0 total_spent: '0' display_total_spent: "$0.00" last_order_completed_at: meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: post: summary: Create a customer tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Creates a customer. No welcome email is sent automatically. **Required scope:** `write_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const customer = await client.customers.create({ email: 'jane@example.com', first_name: 'Jane', last_name: 'Doe', phone: '+1 212 555 1234', tags: ['wholesale'], accepts_email_marketing: true, }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '201': description: customer created content: application/json: example: id: cus_gbHJdmfrXB email: newcustomer@example.com first_name: New last_name: Customer phone: accepts_email_marketing: false full_name: New Customer available_store_credit_total: '0' display_available_store_credit_total: "$0.00" login: metadata: {} last_sign_in_at: current_sign_in_at: created_at: '2026-06-12T17:24:07.836Z' updated_at: '2026-06-12T17:24:07.836Z' sign_in_count: 0 failed_attempts: 0 last_sign_in_ip: current_sign_in_ip: tags: [] internal_note_html: default_billing_address_id: default_shipping_address_id: orders_count: 0 total_spent: '0.0' display_total_spent: "$0.00" last_order_completed_at: requestBody: content: application/json: schema: type: object required: - email properties: email: type: string example: new@example.com first_name: type: string last_name: type: string phone: type: string accepts_email_marketing: type: boolean internal_note: type: string tags: type: array items: type: string metadata: type: object "/api/v3/admin/customers/{id}": get: summary: Show a customer tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Returns full customer details including computed order stats (orders_count, total_spent, last_order_completed_at). **Required scope:** `read_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const customer = await client.customers.get('cus_UkLWZg9DAJ', { expand: ['addresses', 'store_credits'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true description: Customer ID schema: type: string - name: expand in: query required: false description: 'Comma-separated associations: addresses, orders, store_credits, default_billing_address, default_shipping_address' schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., email,first_name,last_name). id is always included. schema: type: string responses: '200': description: customer found content: application/json: example: id: cus_UkLWZg9DAJ email: jane@example.com first_name: Jane last_name: Doe phone: accepts_email_marketing: false full_name: Jane Doe available_store_credit_total: '0' display_available_store_credit_total: "$0.00" login: jane@example.com metadata: {} last_sign_in_at: current_sign_in_at: created_at: '2026-06-12T17:24:08.112Z' updated_at: '2026-06-12T17:24:08.112Z' sign_in_count: 0 failed_attempts: 0 last_sign_in_ip: current_sign_in_ip: tags: [] internal_note_html: default_billing_address_id: default_shipping_address_id: orders_count: 0 total_spent: '0' display_total_spent: "$0.00" last_order_completed_at: patch: summary: Update a customer tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Updates customer attributes. `tags` replaces the full set. **Required scope:** `write_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const customer = await client.customers.update('cus_UkLWZg9DAJ', { first_name: 'Updated', tags: ['wholesale', 'vip'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '200': description: customer updated content: application/json: example: id: cus_UkLWZg9DAJ email: jane@example.com first_name: Updated last_name: Doe phone: accepts_email_marketing: false full_name: Updated Doe available_store_credit_total: '0' display_available_store_credit_total: "$0.00" login: jane@example.com metadata: {} last_sign_in_at: current_sign_in_at: created_at: '2026-06-12T17:24:08.673Z' updated_at: '2026-06-12T17:24:08.959Z' sign_in_count: 0 failed_attempts: 0 last_sign_in_ip: current_sign_in_ip: tags: [] internal_note_html: default_billing_address_id: default_shipping_address_id: orders_count: 0 total_spent: '0.0' display_total_spent: "$0.00" last_order_completed_at: requestBody: content: application/json: schema: type: object properties: email: type: string first_name: type: string last_name: type: string phone: type: string accepts_email_marketing: type: boolean internal_note: type: string tags: type: array items: type: string metadata: type: object delete: summary: Delete a customer tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Deletes a customer. Returns 422 if the customer has any orders. **Required scope:** `write_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.customers.delete('cus_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '204': description: customer deleted "/api/v3/admin/customers/bulk_add_to_groups": post: summary: Bulk-add customers to groups tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Attaches each customer in `ids` to every group in `customer_group_ids`. Idempotent — customers already in a group are skipped server-side. Groups from sibling stores are silently ignored. Returns counts of customers and groups that were processed (post store-scoping). **Required scope:** `write_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const result = await client.customers.bulkAddToGroups({ ids: ['cus_UkLWZg9DAJ', 'cus_QrLWXg9CAJ'], customer_group_ids: ['cg_UkLWZg9DAJ'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: customers added to groups content: application/json: example: customer_count: 1 customer_group_count: 1 schema: type: object properties: customer_count: type: integer customer_group_count: type: integer requestBody: content: application/json: schema: type: object required: - ids - customer_group_ids properties: ids: type: array items: type: string example: - cus_UkLWZg9DAJ - cus_QrLWXg9CAJ customer_group_ids: type: array items: type: string example: - cg_UkLWZg9DAJ "/api/v3/admin/customers/bulk_remove_from_groups": post: summary: Bulk-remove customers from groups tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Detaches each customer in `ids` from every group in `customer_group_ids`. No-op for non-members. Groups from sibling stores are silently ignored. **Required scope:** `write_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const result = await client.customers.bulkRemoveFromGroups({ ids: ['cus_UkLWZg9DAJ'], customer_group_ids: ['cg_UkLWZg9DAJ'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: customers removed from groups content: application/json: example: customer_count: 1 customer_group_count: 1 schema: type: object properties: customer_count: type: integer customer_group_count: type: integer requestBody: content: application/json: schema: type: object required: - ids - customer_group_ids properties: ids: type: array items: type: string example: - cus_UkLWZg9DAJ customer_group_ids: type: array items: type: string example: - cg_UkLWZg9DAJ "/api/v3/admin/customers/bulk_add_tags": post: summary: Bulk-add tags to customers tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Adds each tag name in `tags` to every customer in `ids`. Tags are upserted by name; re-adding an existing tag is a no-op. **Required scope:** `write_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const result = await client.customers.bulkAddTags({ ids: ['cus_UkLWZg9DAJ', 'cus_QrLWXg9CAJ'], tags: ['vip', 'newsletter'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: tags added content: application/json: example: customer_count: 1 tag_count: 2 schema: type: object properties: customer_count: type: integer tag_count: type: integer requestBody: content: application/json: schema: type: object required: - ids - tags properties: ids: type: array items: type: string example: - cus_UkLWZg9DAJ tags: type: array items: type: string example: - vip - newsletter "/api/v3/admin/customers/bulk_remove_tags": post: summary: Bulk-remove tags from customers tags: - Customers security: - api_key: [] bearer_auth: [] description: |- Removes each tag name in `tags` from every customer in `ids`. No-op for customers that don't carry the tag. **Required scope:** `write_customers` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const result = await client.customers.bulkRemoveTags({ ids: ['cus_UkLWZg9DAJ'], tags: ['vip'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: tags removed content: application/json: example: customer_count: 1 tag_count: 1 schema: type: object properties: customer_count: type: integer tag_count: type: integer requestBody: content: application/json: schema: type: object required: - ids - tags properties: ids: type: array items: type: string example: - cus_UkLWZg9DAJ tags: type: array items: type: string example: - vip "/api/v3/admin/exports": get: summary: List exports tags: - Exports security: - api_key: [] bearer_auth: [] description: |- Returns CSV exports queued or completed for the current store. Polled by the admin SPA to detect when an export finishes (`done: true`). **Required scope:** the read scope of the exported resource — `read_products` for product exports, `read_customers` for customer exports, etc. (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: exports } = await client.exports.list() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: exports found content: application/json: example: data: - id: exp_UkLWZg9DAJ number: EF801500147 type: Spree::Exports::Products format: csv created_at: '2026-06-12T17:24:13.131Z' updated_at: '2026-06-12T17:24:13.131Z' user_id: admin_UkLWZg9DAJ done: false filename: byte_size: download_url: meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: post: summary: Create an export tags: - Exports security: - api_key: [] bearer_auth: [] description: |- Queues a CSV export. The `type` selects the dataset; `search_params` is an optional Ransack query (same shape used by the `q[...]` params on list endpoints) that filters which records are exported. Pass `record_selection: "all"` to clear the filter server-side and export everything in scope. Generation is asynchronous. Poll `GET /admin/exports/{id}` until `done` is `true`, then redirect the browser to `download_url` to fetch the file. **Required scope:** the read scope of the exported resource — `read_products` for product exports, `read_customers` for customer exports, etc. (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const exp = await client.exports.create({ type: 'Spree::Exports::Products', search_params: { name_cont: 'shirt' } }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '201': description: export queued content: application/json: example: id: exp_gbHJdmfrXB number: EF876181108 type: Spree::Exports::Products format: csv created_at: '2026-06-12T17:24:13.433Z' updated_at: '2026-06-12T17:24:13.433Z' user_id: admin_UkLWZg9DAJ done: false filename: byte_size: download_url: requestBody: content: application/json: schema: type: object required: - type properties: type: type: string enum: - Spree::Exports::Products - Spree::Exports::Orders - Spree::Exports::Customers - Spree::Exports::ProductTranslations - Spree::Exports::GiftCards - Spree::Exports::CouponCodes - Spree::Exports::NewsletterSubscribers example: Spree::Exports::Products record_selection: type: string enum: - filtered - all description: Set to "all" to ignore search_params and export everything in scope. example: filtered search_params: type: object description: Ransack query hash. Same predicates accepted by the list endpoint. example: name_cont: shirt additionalProperties: true "/api/v3/admin/exports/{id}": get: summary: Show an export tags: - Exports security: - api_key: [] bearer_auth: [] description: |- Returns export status. While `done` is `false`, the SPA continues polling. **Required scope:** the read scope of the exported resource — `read_products` for product exports, `read_customers` for customer exports, etc. (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const exp = await client.exports.get('exp_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '200': description: export found content: application/json: example: id: exp_UkLWZg9DAJ number: EF904215811 type: Spree::Exports::Products format: csv created_at: '2026-06-12T17:24:13.722Z' updated_at: '2026-06-12T17:24:13.722Z' user_id: admin_UkLWZg9DAJ done: false filename: byte_size: download_url: delete: summary: Delete an export tags: - Exports security: - api_key: [] bearer_auth: [] description: |- Removes the export and purges its attachment. **Required scope:** the read scope of the exported resource — `read_products` for product exports, `read_customers` for customer exports, etc. (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.exports.delete('exp_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '204': description: export deleted "/api/v3/admin/exports/{id}/download": get: summary: Download an export tags: - Exports security: - api_key: [] bearer_auth: [] description: |- Streams the exported CSV with `Content-Disposition: attachment`. Returns 422 with `code: export_not_ready` while `done` is still `false`. The endpoint is JWT/API-key protected, so SPA clients must fetch it (with `Authorization` header) and trigger the browser download via a Blob URL — a top-level navigation cannot carry the JWT. **Required scope:** the read scope of the exported resource — `read_products` for product exports, `read_customers` for customer exports, etc. (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) // Fetch with the Bearer token, then drive the browser download: const res = await fetch(exp.download_url, { headers: { Authorization: `Bearer ${token}` } }) const blob = await res.blob() const url = URL.createObjectURL(blob) const a = Object.assign(document.createElement('a'), { href: url, download: exp.filename }) a.click() URL.revokeObjectURL(url) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '200': description: CSV file content: application/json: {} text/csv: schema: type: string format: binary "/api/v3/admin/orders/{order_id}/fulfillments": get: summary: List fulfillments tags: - Fulfillments security: - api_key: [] bearer_auth: [] description: |- Returns all shipments for an order. **Required scope:** `read_fulfillments` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: fulfillments } = await client.orders.fulfillments.list('or_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., inventory_units, stock_location, shipping_rates). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., number,status,tracking,cost). id is always included. schema: type: string responses: '200': description: fulfillments found content: application/json: example: data: - id: ful_UkLWZg9DAJ number: H35590720789 tracking: U10000 tracking_url: cost: '10.0' display_cost: "$10.00" total: '10.0' display_total: "$10.00" discount_total: '0.0' display_discount_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" status: ready fulfillment_type: shipping fulfilled_at: items: - item_id: li_UkLWZg9DAJ variant_id: variant_UkLWZg9DAJ quantity: 1 metadata: {} adjustment_total: '0.0' pre_tax_amount: '0.0' created_at: '2026-06-12T17:24:25.258Z' updated_at: '2026-06-12T17:24:25.352Z' order_id: or_UkLWZg9DAJ stock_location_id: sloc_UkLWZg9DAJ meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: "/api/v3/admin/orders/{order_id}/fulfillments/{id}": get: summary: Show a shipment tags: - Fulfillments security: - api_key: [] bearer_auth: [] description: |- Returns details of a specific shipment. **Required scope:** `read_fulfillments` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const fulfillment = await client.orders.fulfillments.get('or_UkLWZg9DAJ', 'ful_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: id in: path required: true description: Fulfillment ID schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., inventory_units, stock_location, shipping_rates). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., number,status,tracking,cost). id is always included. schema: type: string responses: '200': description: shipment found content: application/json: example: id: ful_UkLWZg9DAJ number: H01928147257 tracking: U10000 tracking_url: cost: '10.0' display_cost: "$10.00" total: '10.0' display_total: "$10.00" discount_total: '0.0' display_discount_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" status: ready fulfillment_type: shipping fulfilled_at: items: - item_id: li_UkLWZg9DAJ variant_id: variant_UkLWZg9DAJ quantity: 1 metadata: {} adjustment_total: '0.0' pre_tax_amount: '0.0' created_at: '2026-06-12T17:24:25.980Z' updated_at: '2026-06-12T17:24:26.039Z' order_id: or_UkLWZg9DAJ stock_location_id: sloc_UkLWZg9DAJ patch: summary: Update a shipment tags: - Fulfillments security: - api_key: [] bearer_auth: [] description: |- Updates a shipment (tracking, shipping rate). **Required scope:** `write_fulfillments` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const fulfillment = await client.orders.fulfillments.update('or_UkLWZg9DAJ', 'ful_UkLWZg9DAJ', { tracking: '1Z999AA10123456784', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: id in: path required: true description: Fulfillment ID schema: type: string responses: '200': description: shipment updated content: application/json: example: id: ful_UkLWZg9DAJ number: H47992763995 tracking: 1Z999AA10123456784 tracking_url: https://wwwapps.ups.com/WebTracking/track?track=yes&trackNums=1Z999AA10123456784 cost: '10.0' display_cost: "$10.00" total: '10.0' display_total: "$10.00" discount_total: '0.0' display_discount_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" status: ready fulfillment_type: shipping fulfilled_at: items: - item_id: li_UkLWZg9DAJ variant_id: variant_UkLWZg9DAJ quantity: 1 metadata: {} adjustment_total: '0.0' pre_tax_amount: '0.0' created_at: '2026-06-12T17:24:26.652Z' updated_at: '2026-06-12T17:24:27.050Z' order_id: or_UkLWZg9DAJ stock_location_id: sloc_UkLWZg9DAJ requestBody: content: application/json: schema: type: object properties: tracking: type: string example: 1Z999AA10123456784 selected_shipping_rate_id: type: string "/api/v3/admin/orders/{order_id}/fulfillments/{id}/fulfill": patch: summary: Fulfill a fulfillment tags: - Fulfillments security: - api_key: [] bearer_auth: [] description: |- Marks a fulfillment as fulfilled. **Required scope:** `write_fulfillments` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const fulfillment = await client.orders.fulfillments.fulfill('or_UkLWZg9DAJ', 'ful_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: id in: path required: true description: Fulfillment ID schema: type: string responses: '200': description: fulfillment fulfilled content: application/json: example: id: ful_UkLWZg9DAJ number: H21297889426 tracking: U10000 tracking_url: cost: '10.0' display_cost: "$10.00" total: '10.0' display_total: "$10.00" discount_total: '0.0' display_discount_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" status: shipped fulfillment_type: shipping fulfilled_at: '2026-06-12T17:24:27Z' items: - item_id: li_UkLWZg9DAJ variant_id: variant_UkLWZg9DAJ quantity: 1 metadata: {} adjustment_total: '0.0' pre_tax_amount: '0.0' created_at: '2026-06-12T17:24:27.408Z' updated_at: '2026-06-12T17:24:27.765Z' order_id: or_UkLWZg9DAJ stock_location_id: sloc_UkLWZg9DAJ "/api/v3/admin/orders/{order_id}/fulfillments/{id}/cancel": patch: summary: Cancel a fulfillment tags: - Fulfillments security: - api_key: [] bearer_auth: [] description: |- Cancels a fulfillment. **Required scope:** `write_fulfillments` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const fulfillment = await client.orders.fulfillments.cancel('or_UkLWZg9DAJ', 'ful_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: id in: path required: true description: Fulfillment ID schema: type: string responses: '200': description: fulfillment canceled content: application/json: example: id: ful_UkLWZg9DAJ number: H36610642534 tracking: U10000 tracking_url: cost: '10.0' display_cost: "$10.00" total: '10.0' display_total: "$10.00" discount_total: '0.0' display_discount_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" status: canceled fulfillment_type: shipping fulfilled_at: items: - item_id: li_UkLWZg9DAJ variant_id: variant_UkLWZg9DAJ quantity: 1 metadata: {} adjustment_total: '0.0' pre_tax_amount: '0.0' created_at: '2026-06-12T17:24:28.103Z' updated_at: '2026-06-12T17:24:28.447Z' order_id: or_UkLWZg9DAJ stock_location_id: sloc_UkLWZg9DAJ "/api/v3/admin/orders/{order_id}/fulfillments/{id}/resume": patch: summary: Resume a fulfillment tags: - Fulfillments security: - api_key: [] bearer_auth: [] description: |- Resumes a canceled fulfillment. **Required scope:** `write_fulfillments` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const fulfillment = await client.orders.fulfillments.resume('or_UkLWZg9DAJ', 'ful_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: id in: path required: true description: Fulfillment ID schema: type: string responses: '200': description: fulfillment resumed content: application/json: example: id: ful_UkLWZg9DAJ number: H84093050628 tracking: U10000 tracking_url: cost: '10.0' display_cost: "$10.00" total: '10.0' display_total: "$10.00" discount_total: '0.0' display_discount_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" status: pending fulfillment_type: shipping fulfilled_at: items: - item_id: li_UkLWZg9DAJ variant_id: variant_UkLWZg9DAJ quantity: 1 metadata: {} adjustment_total: '0.0' pre_tax_amount: '0.0' created_at: '2026-06-12T17:24:28.839Z' updated_at: '2026-06-12T17:24:29.213Z' order_id: or_UkLWZg9DAJ stock_location_id: sloc_UkLWZg9DAJ "/api/v3/admin/orders/{order_id}/fulfillments/{id}/split": patch: summary: Split a fulfillment tags: - Fulfillments security: - api_key: [] bearer_auth: [] description: |- Transfers items from this shipment to a new shipment at a different stock location. **Required scope:** `write_fulfillments` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const fulfillment = await client.orders.fulfillments.split('or_UkLWZg9DAJ', 'ful_UkLWZg9DAJ', { quantity: 1, }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: id in: path required: true description: Fulfillment ID schema: type: string responses: '200': description: fulfillment split content: application/json: example: data: - id: ful_gbHJdmfrXB number: H94460401316 tracking: tracking_url: cost: '10.0' display_cost: "$10.00" total: '10.0' display_total: "$10.00" discount_total: '0.0' display_discount_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" status: ready fulfillment_type: shipping fulfilled_at: items: - item_id: li_UkLWZg9DAJ variant_id: variant_UkLWZg9DAJ quantity: 1 metadata: {} adjustment_total: '0.0' pre_tax_amount: '0.0' created_at: '2026-06-12T17:24:29.915Z' updated_at: '2026-06-12T17:24:29.963Z' order_id: or_UkLWZg9DAJ stock_location_id: sloc_gbHJdmfrXB requestBody: content: application/json: schema: type: object required: - variant_id - quantity properties: variant_id: type: string description: Variant ID quantity: type: integer example: 1 stock_location_id: type: string description: Target stock location ID "/api/v3/admin/gift_card_batches": get: summary: List gift card batches tags: - Gift Cards security: - api_key: [] bearer_auth: [] description: |- Returns the gift card batches issued by the current store. Each batch groups the cards generated together for a campaign or bulk-issuance — the cards themselves live under `/admin/gift_cards` and reference the batch via `gift_card_batch_id`. **Required scope:** `read_gift_cards` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: batches } = await client.giftCardBatches.list({ page: 1, limit: 25 }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: page in: query required: false description: Page number schema: type: integer - name: limit in: query required: false description: Records per page schema: type: integer - name: q[prefix_cont] in: query required: false description: Filter by prefix (contains) schema: type: string - name: sort in: query required: false description: Sort by field. Prefix with `-` for descending. schema: type: string responses: '200': description: gift card batches found content: application/json: example: data: - id: gcb_UkLWZg9DAJ codes_count: 2 currency: USD prefix: WELCOME created_at: '2026-06-12T17:24:14.398Z' updated_at: '2026-06-12T17:24:14.398Z' amount: '50.0' expires_at: created_by_id: meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: schema: type: object properties: data: type: array items: "$ref": "#/components/schemas/GiftCardBatch" meta: "$ref": "#/components/schemas/PaginationMeta" required: - data - meta post: summary: Create a gift card batch tags: - Gift Cards security: - api_key: [] bearer_auth: [] description: |- Issues a batch of gift cards in a single call. The server generates `codes_count` cards inline for small batches (configurable via `Spree.config.gift_card_batch_web_limit`, default 500) or enqueues a background job for larger ones. Each card's code is the batch `prefix` followed by random hex. **Required scope:** `write_gift_cards` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const batch = await client.giftCardBatches.create({ prefix: 'WELCOME', amount: '25.00', currency: 'USD', codes_count: 100, expires_at: '2030-12-31', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '201': description: gift card batch created content: application/json: example: id: gcb_gbHJdmfrXB codes_count: 5 currency: USD prefix: NEWCAMP created_at: '2026-06-12T17:24:14.972Z' updated_at: '2026-06-12T17:24:14.972Z' amount: '25.0' expires_at: '2030-12-31' created_by_id: admin_UkLWZg9DAJ schema: "$ref": "#/components/schemas/GiftCardBatch" '422': description: validation error content: application/json: example: error: code: validation_error message: Prefix can't be blank details: prefix: - can't be blank schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object required: - prefix - amount - codes_count properties: prefix: type: string example: WELCOME description: Lowercased and prepended to every generated code. amount: type: string example: '25.00' description: Decimal amount per card, greater than zero. currency: type: string example: USD description: ISO 4217 currency code. Defaults to the store currency. codes_count: type: integer example: 100 description: Number of cards to generate. Capped at `gift_card_batch_limit`. expires_at: type: string example: '2030-12-31' nullable: true "/api/v3/admin/gift_card_batches/{id}": parameters: - name: id in: path required: true description: Gift card batch prefixed ID schema: type: string get: summary: Get a gift card batch tags: - Gift Cards security: - api_key: [] bearer_auth: [] description: |- Returns a single batch. **Required scope:** `read_gift_cards` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const batch = await client.giftCardBatches.get('gcb_K3zr8x') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: gift card batch found content: application/json: example: id: gcb_UkLWZg9DAJ codes_count: 2 currency: USD prefix: WELCOME created_at: '2026-06-12T17:24:15.269Z' updated_at: '2026-06-12T17:24:15.269Z' amount: '50.0' expires_at: created_by_id: schema: "$ref": "#/components/schemas/GiftCardBatch" '404': description: gift card batch not found content: application/json: example: error: code: record_not_found message: Gift card batch not found schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v3/admin/gift_cards": get: summary: List gift cards tags: - Gift Cards security: - api_key: [] bearer_auth: [] description: |- Returns the gift cards issued by the current store. Filter by `q[code_cont]` for code search, `q[user_id_eq]` for cards issued to a specific customer, or `q[state_eq]` for status filtering. **Required scope:** `read_gift_cards` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: giftCards } = await client.giftCards.list({ page: 1, limit: 25, expand: ['customer', 'created_by'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: page in: query required: false description: Page number schema: type: integer - name: limit in: query required: false description: Number of records per page schema: type: integer - name: q[code_cont] in: query required: false description: Filter by gift card code (contains) schema: type: string - name: q[state_eq] in: query required: false description: Filter by status (active, redeemed, partially_redeemed, canceled) schema: type: string - name: sort in: query required: false description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include. id is always included. schema: type: string responses: '200': description: gift cards found content: application/json: example: data: - id: gc_UkLWZg9DAJ code: CD084BB41D246D4F status: active currency: USD amount: '50.0' amount_used: '0.0' amount_authorized: '0.0' amount_remaining: '50.0' display_amount: "$50.00" display_amount_used: "$0.00" display_amount_remaining: "$50.00" expires_at: redeemed_at: expired: false active: true created_at: '2026-06-12T17:24:15.844Z' updated_at: '2026-06-12T17:24:15.844Z' customer_id: created_by_id: - id: gc_gbHJdmfrXB code: 1942CCC0C95DF267 status: active currency: USD amount: '25.0' amount_used: '0.0' amount_authorized: '0.0' amount_remaining: '25.0' display_amount: "$25.00" display_amount_used: "$0.00" display_amount_remaining: "$25.00" expires_at: redeemed_at: expired: false active: true created_at: '2026-06-12T17:24:15.846Z' updated_at: '2026-06-12T17:24:15.846Z' customer_id: created_by_id: meta: page: 1 limit: 25 count: 2 pages: 1 from: 1 to: 2 in: 2 previous: next: schema: type: object properties: data: type: array items: "$ref": "#/components/schemas/GiftCard" meta: "$ref": "#/components/schemas/PaginationMeta" required: - data - meta '401': description: unauthorized content: application/json: example: error: code: authentication_required message: Authentication required schema: "$ref": "#/components/schemas/ErrorResponse" post: summary: Create a gift card tags: - Gift Cards security: - api_key: [] bearer_auth: [] description: |- Issues a gift card scoped to the current store. The code is auto-generated when omitted. `currency` defaults to the store's configured currency. Pass `user_id` (prefixed ID) to attach the card to a specific customer. **Required scope:** `write_gift_cards` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const giftCard = await client.giftCards.create({ amount: '25.00', currency: 'USD', expires_at: '2030-12-31', user_id: 'cus_UkLWZg9DAJ', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '201': description: gift card created content: application/json: example: id: gc_EfhxLZ9ck8 code: 4F5E5C544DDFA6B5 status: active currency: USD amount: '25.0' amount_used: '0.0' amount_authorized: '0.0' amount_remaining: '25.0' display_amount: "$25.00" display_amount_used: "$0.00" display_amount_remaining: "$25.00" expires_at: '2030-12-31' redeemed_at: expired: false active: true created_at: '2026-06-12T17:24:16.432Z' updated_at: '2026-06-12T17:24:16.432Z' customer_id: created_by_id: admin_UkLWZg9DAJ schema: "$ref": "#/components/schemas/GiftCard" '422': description: validation error content: application/json: example: error: code: validation_error message: Amount must be greater than 0 details: amount: - must be greater than 0 schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object required: - amount properties: amount: type: string example: '25.00' description: Decimal amount, greater than zero. currency: type: string example: USD description: ISO 4217 currency code. Defaults to the store currency. code: type: string example: WELCOME50 description: Optional caller-supplied code. Auto-generated when omitted. expires_at: type: string example: '2030-12-31' description: ISO 8601 date. nullable: true user_id: type: string example: cus_UkLWZg9DAJ description: Optional customer prefixed ID. nullable: true "/api/v3/admin/gift_cards/{id}": parameters: - name: id in: path required: true description: Gift card prefixed ID schema: type: string get: summary: Get a gift card tags: - Gift Cards security: - api_key: [] bearer_auth: [] description: |- Returns a single gift card. **Required scope:** `read_gift_cards` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const giftCard = await client.giftCards.get('gc_K3zr8x', { expand: ['customer', 'created_by', 'orders'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include. id is always included. schema: type: string responses: '200': description: gift card found content: application/json: example: id: gc_UkLWZg9DAJ code: CF2E19F27E7DA895 status: active currency: USD amount: '50.0' amount_used: '0.0' amount_authorized: '0.0' amount_remaining: '50.0' display_amount: "$50.00" display_amount_used: "$0.00" display_amount_remaining: "$50.00" expires_at: redeemed_at: expired: false active: true created_at: '2026-06-12T17:24:16.734Z' updated_at: '2026-06-12T17:24:16.734Z' customer_id: created_by_id: schema: "$ref": "#/components/schemas/GiftCard" '404': description: gift card not found content: application/json: example: error: code: record_not_found message: Gift card not found schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update a gift card tags: - Gift Cards security: - api_key: [] bearer_auth: [] description: |- Updates an active gift card's editable attributes. Redeemed or partially-redeemed cards cannot be edited. **Required scope:** `write_gift_cards` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const giftCard = await client.giftCards.update('gc_K3zr8x', { amount: '75.00', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: gift card updated content: application/json: example: id: gc_UkLWZg9DAJ code: 38197D3D485C7386 status: active currency: USD amount: '75.0' amount_used: '0.0' amount_authorized: '0.0' amount_remaining: '75.0' display_amount: "$75.00" display_amount_used: "$0.00" display_amount_remaining: "$75.00" expires_at: redeemed_at: expired: false active: true created_at: '2026-06-12T17:24:17.340Z' updated_at: '2026-06-12T17:24:17.626Z' customer_id: created_by_id: schema: "$ref": "#/components/schemas/GiftCard" requestBody: content: application/json: schema: type: object properties: amount: type: string example: '75.00' expires_at: type: string example: '2031-12-31' nullable: true user_id: type: string example: cus_UkLWZg9DAJ nullable: true delete: summary: Delete a gift card tags: - Gift Cards security: - api_key: [] bearer_auth: [] description: |- Deletes an unused gift card. Cards that have been redeemed or partially redeemed cannot be deleted and return 422. **Required scope:** `write_gift_cards` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.giftCards.delete('gc_K3zr8x') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '204': description: gift card deleted '422': description: redeemed gift card cannot be deleted content: application/json: example: error: code: validation_error message: Gift card cannot be deleted "/api/v3/admin/markets": get: summary: List markets tags: - Markets security: - api_key: [] bearer_auth: [] description: |- Returns the markets configured for the current store. Markets are store-scoped and ordered by `position` (an `acts_as_list` column — update the order via `PATCH /markets/{id}` with `position`). **Required scope:** `read_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: markets } = await client.markets.list() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: page in: query required: false schema: type: integer - name: limit in: query required: false schema: type: integer - name: q[name_cont] in: query required: false schema: type: string - name: sort in: query required: false schema: type: string - name: expand in: query required: false description: 'Comma-separated associations to embed. Supported: `countries`.' schema: type: string responses: '200': description: markets found content: application/json: example: data: - id: mkt_UkLWZg9DAJ name: EU currency: USD default_locale: en tax_inclusive: false default: false country_isos: - DE supported_locales: - en created_at: '2026-06-12T17:24:19.453Z' updated_at: '2026-06-12T17:24:19.453Z' meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: schema: type: object properties: data: type: array items: "$ref": "#/components/schemas/Market" meta: "$ref": "#/components/schemas/PaginationMeta" required: - data - meta post: summary: Create a market tags: - Markets security: - api_key: [] bearer_auth: [] description: |- Creates a new market for the current store. - `country_isos` accepts 2-letter ISO country codes (e.g. `["DE", "FR"]`); the market must contain at least one country. Unknown codes are silently dropped. - `supported_locales` accepts an array of locale codes; the `default_locale` is always implicitly included. - Setting `default: true` automatically demotes the previous default market in the store. **Required scope:** `write_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const market = await client.markets.create({ name: 'Europe', currency: 'EUR', default_locale: 'de', supported_locales: ['de', 'en', 'fr'], tax_inclusive: true, country_isos: ['DE', 'FR', 'IT'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '201': description: market created content: application/json: example: id: mkt_gbHJdmfrXB name: France only currency: EUR default_locale: fr tax_inclusive: true default: false country_isos: - FR supported_locales: - en - fr created_at: '2026-06-12T17:24:20.056Z' updated_at: '2026-06-12T17:24:20.056Z' schema: "$ref": "#/components/schemas/Market" '422': description: validation error content: application/json: example: error: code: validation_error message: Name can't be blank, Currency can't be blank, Default locale can't be blank, and Countries can't be blank details: name: - can't be blank currency: - can't be blank default_locale: - can't be blank countries: - can't be blank schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: name: type: string example: Europe currency: type: string example: EUR description: ISO 4217 currency code. default_locale: type: string example: de description: IETF locale tag used as the market default. supported_locales: type: array items: type: string description: Locale codes available in this market. The default is always implicitly included. example: - de - en tax_inclusive: type: boolean default: false description: Display prices with tax included. default: type: boolean default: false description: Setting to true demotes the previous default. position: type: integer description: Sort order within the store; lower = first. country_isos: type: array items: type: string description: 2-letter ISO country codes assigned to this market. At least one is required. example: - DE - FR required: - name - currency - default_locale - country_isos "/api/v3/admin/markets/{id}": parameters: - name: id in: path required: true schema: type: string get: summary: Get a market tags: - Markets security: - api_key: [] bearer_auth: [] description: "**Required scope:** `read_settings` (for API-key authentication)." x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const market = await client.markets.get('market_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: expand in: query required: false schema: type: string responses: '200': description: market found content: application/json: example: id: mkt_UkLWZg9DAJ name: EU currency: USD default_locale: en tax_inclusive: false default: false country_isos: - DE supported_locales: - en created_at: '2026-06-12T17:24:20.399Z' updated_at: '2026-06-12T17:24:20.399Z' schema: "$ref": "#/components/schemas/Market" '404': description: market not found content: application/json: example: error: code: record_not_found message: Market not found schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update a market tags: - Markets security: - api_key: [] bearer_auth: [] description: |- Updates an existing market. Pass `country_isos` to replace the market's country list (full-set update), `supported_locales` to replace the supported locales, or `position` to reorder the market within the store. Setting `default: true` automatically demotes the previous default. **Required scope:** `write_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) // `country_isos` is a full-set update — the market is reconciled to match // the array (adds new countries, removes ones not present). Setting // `default: true` demotes the previous default market in the store. const market = await client.markets.update('market_UkLWZg9DAJ', { name: 'European Union', tax_inclusive: true, country_isos: ['DE', 'FR'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: market updated content: application/json: example: id: mkt_UkLWZg9DAJ name: European Union currency: USD default_locale: en tax_inclusive: true default: false country_isos: - DE supported_locales: - en created_at: '2026-06-12T17:24:21.018Z' updated_at: '2026-06-12T17:24:21.314Z' schema: "$ref": "#/components/schemas/Market" '422': description: validation error content: application/json: example: error: code: validation_error message: Name can't be blank details: name: - can't be blank schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: name: type: string currency: type: string default_locale: type: string supported_locales: type: array items: type: string tax_inclusive: type: boolean default: type: boolean position: type: integer country_isos: type: array items: type: string delete: summary: Delete a market tags: - Markets security: - api_key: [] bearer_auth: [] description: |- Soft-deletes the market (sets `deleted_at`). The default market and the last remaining market in a store cannot be deleted — both return 422 with a `validation_error`. **Required scope:** `write_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) // Soft-deletes the market (sets `deleted_at`). The default market and the // last remaining market in a store cannot be deleted — both return 422. await client.markets.delete('market_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '204': description: market deleted '422': description: cannot delete default or last market content: application/json: example: error: code: validation_error message: Market cannot be deleted "/api/v3/admin/option_types": get: summary: List option types tags: - Option Types security: - api_key: [] bearer_auth: [] description: |- Returns a paginated list of option types. **Required scope:** `read_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: optionTypes } = await client.optionTypes.list() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: page in: query required: false description: Page number schema: type: integer - name: limit in: query required: false description: Number of records per page schema: type: integer - name: q[name_cont] in: query required: false description: Filter by name (contains) schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., option_values). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., name,label,position). id is always included. schema: type: string responses: '200': description: option types found content: application/json: example: data: - id: opt_UkLWZg9DAJ name: foo-size-1 label: Size position: 1 kind: dropdown metadata: {} filterable: true created_at: '2026-06-12T17:24:22.583Z' updated_at: '2026-06-12T17:24:22.583Z' meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: schema: type: object properties: data: type: array items: "$ref": "#/components/schemas/OptionType" meta: "$ref": "#/components/schemas/PaginationMeta" required: - data - meta '401': description: unauthorized content: application/json: example: error: code: authentication_required message: Authentication required schema: "$ref": "#/components/schemas/ErrorResponse" post: summary: Create an option type tags: - Option Types security: - api_key: [] bearer_auth: [] description: |- Creates a new option type. Supports nested option values. Option values can be provided inline and will be created or updated by name. **Required scope:** `write_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const optionType = await client.optionTypes.create({ name: 'color', presentation: 'Color', option_values: [ { name: 'red', presentation: 'Red' }, { name: 'navy', presentation: 'Navy' }, ], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '201': description: option type created content: application/json: example: id: opt_gbHJdmfrXB name: material label: Material position: 2 kind: dropdown metadata: {} filterable: true created_at: '2026-06-12T17:24:23.162Z' updated_at: '2026-06-12T17:24:23.162Z' schema: "$ref": "#/components/schemas/OptionType" '422': description: validation error content: application/json: example: error: code: validation_error message: Name can't be blank and Presentation can't be blank details: name: - can't be blank presentation: - can't be blank schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: name: type: string example: color label: type: string example: Color position: type: integer example: 1 filterable: type: boolean example: true option_values: type: array items: type: object properties: name: type: string example: red label: type: string example: Red position: type: integer required: - name - label "/api/v3/admin/option_types/{id}": get: summary: Get an option type tags: - Option Types security: - api_key: [] bearer_auth: [] description: |- Returns a single option type by ID, including its option values. **Required scope:** `read_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const optionType = await client.optionTypes.get('ot_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: id in: path required: true description: Option type ID schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., option_values). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., name,label,position). id is always included. schema: type: string responses: '200': description: option type found content: application/json: example: id: opt_UkLWZg9DAJ name: foo-size-5 label: Size position: 1 kind: dropdown metadata: {} filterable: true created_at: '2026-06-12T17:24:23.455Z' updated_at: '2026-06-12T17:24:23.455Z' schema: "$ref": "#/components/schemas/OptionType" '404': description: option type not found content: application/json: example: error: code: record_not_found message: Option type not found schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update an option type tags: - Option Types security: - api_key: [] bearer_auth: [] description: |- Updates an option type. Supports updating nested option values. **Required scope:** `write_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const optionType = await client.optionTypes.update('ot_UkLWZg9DAJ', { presentation: 'Updated Presentation', option_values: [ { name: 'red', presentation: 'Crimson' }, ], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: id in: path required: true description: Option type ID schema: type: string responses: '200': description: option type updated content: application/json: example: id: opt_UkLWZg9DAJ name: foo-size-7 label: Updated Label position: 1 kind: dropdown metadata: {} filterable: true created_at: '2026-06-12T17:24:24.039Z' updated_at: '2026-06-12T17:24:24.323Z' schema: "$ref": "#/components/schemas/OptionType" '422': description: validation error content: application/json: example: error: code: validation_error message: Presentation can't be blank details: presentation: - can't be blank schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: name: type: string example: color label: type: string example: Color position: type: integer example: 1 filterable: type: boolean example: true option_values: type: array items: type: object properties: id: type: string description: Existing option value ID to update name: type: string example: red label: type: string example: Red position: type: integer delete: summary: Delete an option type tags: - Option Types security: - api_key: [] bearer_auth: [] description: |- Deletes an option type. **Required scope:** `write_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.optionTypes.delete('ot_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: id in: path required: true description: Option type ID schema: type: string responses: '204': description: option type deleted "/api/v3/admin/orders/{order_id}/gift_cards": post: summary: Apply a gift card to an order tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Applies a gift card by code to the order. Returns the gift card. **Required scope:** `write_gift_cards` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.orders.giftCards.apply('or_UkLWZg9DAJ', { code: 'GIFT-XXXX-YYYY', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string responses: '201': description: gift card applied content: application/json: example: id: gc_UkLWZg9DAJ code: B4A00253F5765132 status: active currency: USD amount: '10.0' amount_used: '10.0' amount_authorized: '0.0' amount_remaining: '0.0' display_amount: "$10.00" display_amount_used: "$10.00" display_amount_remaining: "$0.00" expires_at: redeemed_at: expired: false active: true created_at: '2026-06-12T17:24:30.324Z' updated_at: '2026-06-12T17:24:30.627Z' customer_id: created_by_id: requestBody: content: application/json: schema: type: object required: - code properties: code: type: string description: Gift card code example: GIFT-XXXX-YYYY "/api/v3/admin/orders/{order_id}/gift_cards/{id}": delete: summary: Remove a gift card from an order tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Removes the gift card from the order. **Required scope:** `write_gift_cards` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.orders.giftCards.remove('or_UkLWZg9DAJ', 'gc_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: id in: path required: true description: Gift card ID schema: type: string responses: '204': description: gift card removed "/api/v3/admin/orders/{order_id}/items": get: summary: List order items tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Returns all line items for an order. **Required scope:** `read_orders` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: items } = await client.orders.items.list('or_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., variant, variant.product). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., quantity,price,total). id is always included. schema: type: string responses: '200': description: items found content: application/json: example: data: - id: li_UkLWZg9DAJ variant_id: variant_gbHJdmfrXB quantity: 2 currency: USD name: Product 12496 slug: product-12496 options_text: 'Size: S' price: '10.0' display_price: "$10.00" total: '20.0' display_total: "$20.00" adjustment_total: '0.0' display_adjustment_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" discount_total: '0.0' display_discount_total: "$0.00" pre_tax_amount: '20.0' display_pre_tax_amount: "$20.00" discounted_amount: '20.0' display_discounted_amount: "$20.00" display_compare_at_amount: "$0.00" compare_at_amount: thumbnail_url: option_values: - id: optval_UkLWZg9DAJ option_type_id: opt_UkLWZg9DAJ name: size-1 label: S position: 1 color_code: option_type_name: foo-size-10 option_type_label: Size image_url: metadata: {} created_at: '2026-06-12T17:24:31.334Z' updated_at: '2026-06-12T17:24:31.334Z' digital_links: [] metadata: {} created_at: '2026-06-12T17:24:31.626Z' updated_at: '2026-06-12T17:24:31.626Z' cost_price: '17.0' tax_category_id: taxcat_UkLWZg9DAJ meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: post: summary: Add an item tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Adds a new line item to the order. **Required scope:** `write_orders` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const item = await client.orders.items.create('or_UkLWZg9DAJ', { variant_id: 'variant_k5nR8xLq', quantity: 2, }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string responses: '201': description: item added content: application/json: example: id: li_gbHJdmfrXB variant_id: variant_VqXmZF31wY quantity: 3 currency: USD name: Product 148513 slug: product-148513 options_text: 'Size: S' price: '19.99' display_price: "$19.99" total: '59.97' display_total: "$59.97" adjustment_total: '0.0' display_adjustment_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" discount_total: '0.0' display_discount_total: "$0.00" pre_tax_amount: '59.97' display_pre_tax_amount: "$59.97" discounted_amount: '59.97' display_discounted_amount: "$59.97" display_compare_at_amount: "$0.00" compare_at_amount: thumbnail_url: option_values: - id: optval_gbHJdmfrXB option_type_id: opt_gbHJdmfrXB name: size-3 label: S position: 1 color_code: option_type_name: foo-size-12 option_type_label: Size image_url: metadata: {} created_at: '2026-06-12T17:24:32.569Z' updated_at: '2026-06-12T17:24:32.569Z' digital_links: [] metadata: {} created_at: '2026-06-12T17:24:32.598Z' updated_at: '2026-06-12T17:24:32.598Z' cost_price: '17.0' tax_category_id: taxcat_UkLWZg9DAJ requestBody: content: application/json: schema: type: object required: - variant_id properties: variant_id: type: string description: Prefixed variant ID quantity: type: integer default: 1 "/api/v3/admin/orders/{order_id}/items/{id}": get: summary: Show an item tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Returns details of a specific line item. **Required scope:** `read_orders` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const item = await client.orders.items.get('or_UkLWZg9DAJ', 'li_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: id in: path required: true description: Item ID schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., variant, variant.product). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., quantity,price,total). id is always included. schema: type: string responses: '200': description: item found content: application/json: example: id: li_UkLWZg9DAJ variant_id: variant_gbHJdmfrXB quantity: 2 currency: USD name: Product 158464 slug: product-158464 options_text: 'Size: S' price: '10.0' display_price: "$10.00" total: '20.0' display_total: "$20.00" adjustment_total: '0.0' display_adjustment_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" discount_total: '0.0' display_discount_total: "$0.00" pre_tax_amount: '20.0' display_pre_tax_amount: "$20.00" discounted_amount: '20.0' display_discounted_amount: "$20.00" display_compare_at_amount: "$0.00" compare_at_amount: thumbnail_url: option_values: - id: optval_UkLWZg9DAJ option_type_id: opt_UkLWZg9DAJ name: size-4 label: S position: 1 color_code: option_type_name: foo-size-13 option_type_label: Size image_url: metadata: {} created_at: '2026-06-12T17:24:32.673Z' updated_at: '2026-06-12T17:24:32.673Z' digital_links: [] metadata: {} created_at: '2026-06-12T17:24:32.963Z' updated_at: '2026-06-12T17:24:32.963Z' cost_price: '17.0' tax_category_id: taxcat_UkLWZg9DAJ patch: summary: Update an item tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Updates an order item quantity or metadata. **Required scope:** `write_orders` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const item = await client.orders.items.update('or_UkLWZg9DAJ', 'li_UkLWZg9DAJ', { quantity: 5, }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: id in: path required: true description: Item ID schema: type: string responses: '200': description: item updated content: application/json: example: id: li_UkLWZg9DAJ variant_id: variant_gbHJdmfrXB quantity: 5 currency: USD name: Product 166608 slug: product-166608 options_text: 'Size: S' price: '19.99' display_price: "$19.99" total: '99.95' display_total: "$99.95" adjustment_total: '0.0' display_adjustment_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" discount_total: '0.0' display_discount_total: "$0.00" pre_tax_amount: '99.95' display_pre_tax_amount: "$99.95" discounted_amount: '99.95' display_discounted_amount: "$99.95" display_compare_at_amount: "$0.00" compare_at_amount: thumbnail_url: option_values: - id: optval_UkLWZg9DAJ option_type_id: opt_UkLWZg9DAJ name: size-5 label: S position: 1 color_code: option_type_name: foo-size-14 option_type_label: Size image_url: metadata: {} created_at: '2026-06-12T17:24:33.338Z' updated_at: '2026-06-12T17:24:33.338Z' digital_links: [] metadata: {} created_at: '2026-06-12T17:24:33.640Z' updated_at: '2026-06-12T17:24:33.979Z' cost_price: '17.0' tax_category_id: taxcat_UkLWZg9DAJ requestBody: content: application/json: schema: type: object properties: quantity: type: integer delete: summary: Remove an item tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Removes an item from the order. **Required scope:** `write_orders` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.orders.items.delete('or_UkLWZg9DAJ', 'li_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: id in: path required: true description: Item ID schema: type: string responses: '204': description: line item removed "/api/v3/admin/orders/{order_id}/store_credits": post: summary: Apply customer's store credit to an order tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Applies the order customer's available store credit. When `amount` is omitted, applies up to the order outstanding balance. **Required scope:** `write_store_credits` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const order = await client.orders.storeCredits.apply('or_UkLWZg9DAJ', { amount: 25.00, }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string responses: '201': description: store credit applied content: application/json: example: id: or_UkLWZg9DAJ market_id: channel_id: ch_UkLWZg9DAJ number: R641610767 email: cristi@connelly.biz customer_note: currency: USD locale: en total_quantity: 1 item_total: '10.0' display_item_total: "$10.00" adjustment_total: '0.0' display_adjustment_total: "$0.00" discount_total: '0.0' display_discount_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" total: '110.0' display_total: "$110.00" gift_card_total: '0.0' display_gift_card_total: "$0.00" amount_due: '60.0' display_amount_due: "$60.00" delivery_total: '100.0' display_delivery_total: "$100.00" fulfillment_status: payment_status: completed_at: store_credit_total: '50.0' display_store_credit_total: "-$50.00" covered_by_store_credit: false gift_card: market: status: draft last_ip_address: considered_risky: false confirmation_delivered: false store_owner_notification_delivered: payment_total: '0.0' display_payment_total: "$0.00" metadata: {} canceled_at: approved_at: created_at: '2026-06-12T17:24:41.067Z' updated_at: '2026-06-12T17:24:41.127Z' preferred_stock_location_id: tags: [] internal_note: approver_id: canceler_id: created_by_id: customer_id: cus_UkLWZg9DAJ requestBody: content: application/json: schema: type: object properties: amount: type: number description: Optional explicit amount; defaults to order outstanding balance delete: summary: Remove store credit from an order tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Removes any applied store credit from the order. **Required scope:** `write_store_credits` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.orders.storeCredits.remove('or_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string responses: '204': description: store credit removed "/api/v3/admin/orders": get: summary: List orders tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Returns a paginated list of orders for the current store. **Required scope:** `read_orders` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: orders, meta } = await client.orders.list({ status_eq: 'complete', completed_at_gt: '2026-01-01', sort: '-completed_at', limit: 25, }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: page in: query required: false description: Page number schema: type: integer - name: limit in: query required: false description: Number of records per page schema: type: integer - name: sort in: query required: false description: Sort field (e.g., created_at, -created_at, completed_at) schema: type: string - name: q[state_eq] in: query required: false description: Filter by state (cart, address, delivery, payment, confirm, complete, canceled) schema: type: string - name: q[email_cont] in: query required: false description: Filter by email (contains) schema: type: string - name: q[number_eq] in: query required: false description: Filter by order number schema: type: string - name: q[completed_at_gt] in: query required: false description: Filter by completed after date schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., items, fulfillments, payments, customer, discounts, billing_address, shipping_address). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., number,total,status,completed_at). id is always included. schema: type: string responses: '200': description: orders found content: application/json: example: data: - id: or_UkLWZg9DAJ market_id: channel_id: ch_UkLWZg9DAJ number: R244886130 email: humberto_crist@waters.com customer_note: currency: USD locale: en total_quantity: 0 item_total: '0.0' display_item_total: "$0.00" adjustment_total: '0.0' display_adjustment_total: "$0.00" discount_total: '0.0' display_discount_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" total: '0.0' display_total: "$0.00" gift_card_total: '0.0' display_gift_card_total: "$0.00" amount_due: '0.0' display_amount_due: "$0.00" delivery_total: '0.0' display_delivery_total: "$0.00" fulfillment_status: payment_status: completed_at: store_credit_total: '0.0' display_store_credit_total: "$0.00" covered_by_store_credit: false gift_card: market: status: draft last_ip_address: considered_risky: false confirmation_delivered: false store_owner_notification_delivered: payment_total: '0.0' display_payment_total: "$0.00" metadata: {} canceled_at: approved_at: created_at: '2026-06-12T17:24:43.024Z' updated_at: '2026-06-12T17:24:43.024Z' preferred_stock_location_id: tags: [] internal_note: approver_id: canceler_id: created_by_id: customer_id: cus_UkLWZg9DAJ meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: '401': description: unauthorized content: application/json: example: error: code: authentication_required message: Authentication required schema: "$ref": "#/components/schemas/ErrorResponse" post: summary: Create a draft order tags: - Orders security: - api_key: [] bearer_auth: [] x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) // One-shot order create: customer, items, addresses, market, channel, // notes, metadata, and a coupon code in a single call. Everything // except `email` is optional. const order = await client.orders.create({ email: 'jane@example.com', customer_id: 'cus_UkLWZg9DAJ', // Existing customer; omit for guest orders use_customer_default_address: false, // true to copy the customer's saved addresses currency: 'USD', market_id: 'mkt_UkLWZg9DAJ', channel_id: 'ch_UkLWZg9DAJ', // Optional — defaults to the store's primary channel locale: 'en-US', // Pin the order's preferred fulfillment location. Order Routing's // built-in PreferredLocation rule ranks this location first when // it stocks the cart's items; if it doesn't, routing falls back // to the next rule (Minimize Splits → Default Location). preferred_stock_location_id: 'sloc_UkLWZg9DAJ', customer_note: 'Please leave at the front desk.', internal_note: 'VIP customer — handle with care.', metadata: { external_reference: 'subscription_invoice_2026_04', source: 'recurring-engine', }, // Items: each variant_id + quantity. Optional metadata per line. items: [ { variant_id: 'variant_k5nR8xLq', quantity: 2 }, { variant_id: 'variant_QXyZ12abCD', quantity: 1, metadata: { gift: true } }, ], // Provide addresses inline OR by ID (existing customer addresses). shipping_address: { first_name: 'Jane', last_name: 'Doe', address1: '350 Fifth Avenue', address2: 'Floor 42', city: 'New York', postal_code: '10118', country_iso: 'US', state_abbr: 'NY', phone: '+1 212 555 1234', company: 'Acme Inc.', }, // shipping_address_id: 'addr_UkLWZg9DAJ', // alternative to inline billing_address: { first_name: 'Jane', last_name: 'Doe', address1: '350 Fifth Avenue', city: 'New York', postal_code: '10118', country_iso: 'US', state_abbr: 'NY', phone: '+1 212 555 1234', }, // billing_address_id: 'addr_UkLWZg9DAJ', // Optional. Invalid codes are non-fatal — the order is created either way. coupon_code: 'WELCOME10', }) description: |- Creates a new draft order in one shot. Customer, items, addresses, currency, market, channel, locale, notes, metadata, and a coupon code can all be provided inline. Setting `preferred_stock_location_id` pins the order's preferred fulfillment location — Order Routing's built-in `PreferredLocation` rule consumes it when picking which stock location ships each shipment. Invalid coupon codes are non-fatal — the order is created and the failure is reported on the service result (not in the API response body for now). **Required scope:** `write_orders` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '201': description: order created with preferred_stock_location_id content: application/json: example: id: or_gbHJdmfrXB market_id: channel_id: ch_UkLWZg9DAJ number: R886479771 email: pinned@example.com customer_note: currency: USD locale: en total_quantity: 0 item_total: '0.0' display_item_total: "$0.00" adjustment_total: '0.0' display_adjustment_total: "$0.00" discount_total: '0.0' display_discount_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" total: '0.0' display_total: "$0.00" gift_card_total: '0.0' display_gift_card_total: "$0.00" amount_due: '0.0' display_amount_due: "$0.00" delivery_total: '0.0' display_delivery_total: "$0.00" fulfillment_status: payment_status: completed_at: store_credit_total: '0.0' display_store_credit_total: "$0.00" covered_by_store_credit: false gift_card: market: status: draft last_ip_address: considered_risky: false confirmation_delivered: false store_owner_notification_delivered: payment_total: '0.0' display_payment_total: "$0.00" metadata: {} canceled_at: approved_at: created_at: '2026-06-12T17:24:44.884Z' updated_at: '2026-06-12T17:24:44.888Z' preferred_stock_location_id: sloc_UkLWZg9DAJ tags: [] internal_note: approver_id: canceler_id: created_by_id: customer_id: requestBody: content: application/json: schema: type: object properties: email: type: string example: customer@example.com customer_id: type: string description: 'Customer ID. Alias: user_id (legacy).' use_customer_default_address: type: boolean description: When true with customer_id, copies the customer's saved billing/shipping addresses onto the order. currency: type: string example: USD market_id: type: string description: Market ID channel_id: type: string description: Channel ID. Defaults to the store primary channel when omitted. preferred_stock_location_id: type: string description: Stock Location ID to prefer for fulfillment. Order Routing's built-in PreferredLocation rule reads this and ranks the location first; routing falls back to the next rule when the preferred location can't cover the cart. locale: type: string example: en-US customer_note: type: string description: Public, customer-visible note internal_note: type: string description: Staff-only note metadata: type: object description: Arbitrary key/value metadata shipping_address: type: object properties: first_name: type: string last_name: type: string address1: type: string city: type: string postal_code: type: string country_iso: type: string state_abbr: type: string phone: type: string shipping_address_id: type: string description: Existing customer address ID billing_address: type: object properties: first_name: type: string last_name: type: string address1: type: string city: type: string postal_code: type: string country_iso: type: string state_abbr: type: string phone: type: string billing_address_id: type: string description: Existing customer address ID items: type: array items: type: object required: - variant_id - quantity properties: variant_id: type: string description: Variant ID quantity: type: integer example: 1 metadata: type: object coupon_code: type: string description: Optional. Applied non-fatally; invalid codes do not block creation. "/api/v3/admin/orders/{id}": get: summary: Show an order tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Returns full order details including admin-only fields. **Required scope:** `read_orders` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const order = await client.orders.get('or_UkLWZg9DAJ', { expand: ['items', 'fulfillments', 'payments', 'customer'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: id in: path required: true description: Order ID (e.g., or_xxx) schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., items, fulfillments, payments, customer, discounts, billing_address, shipping_address). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., number,total,status,completed_at). id is always included. schema: type: string responses: '200': description: order found content: application/json: example: id: or_UkLWZg9DAJ market_id: channel_id: ch_UkLWZg9DAJ number: R954821619 email: yasmin_hand@windler.co.uk customer_note: currency: USD locale: en total_quantity: 0 item_total: '0.0' display_item_total: "$0.00" adjustment_total: '0.0' display_adjustment_total: "$0.00" discount_total: '0.0' display_discount_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" total: '0.0' display_total: "$0.00" gift_card_total: '0.0' display_gift_card_total: "$0.00" amount_due: '0.0' display_amount_due: "$0.00" delivery_total: '0.0' display_delivery_total: "$0.00" fulfillment_status: payment_status: completed_at: store_credit_total: '0.0' display_store_credit_total: "$0.00" covered_by_store_credit: false gift_card: market: status: draft last_ip_address: considered_risky: false confirmation_delivered: false store_owner_notification_delivered: payment_total: '0.0' display_payment_total: "$0.00" metadata: {} canceled_at: approved_at: created_at: '2026-06-12T17:24:45.173Z' updated_at: '2026-06-12T17:24:45.173Z' preferred_stock_location_id: tags: [] internal_note: approver_id: canceler_id: created_by_id: customer_id: cus_UkLWZg9DAJ '404': description: order not found content: application/json: example: error: code: order_not_found message: Order not found schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update an order tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Updates an order. Supports updating email, addresses, special instructions, and line items. **Required scope:** `write_orders` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const order = await client.orders.update('or_UkLWZg9DAJ', { email: 'updated@example.com', internal_note: 'VIP — gift wrap on next order', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: id in: path required: true description: Order ID schema: type: string responses: '200': description: order updated content: application/json: example: id: or_UkLWZg9DAJ market_id: channel_id: ch_UkLWZg9DAJ number: R935476385 email: updated@example.com customer_note: currency: USD locale: en total_quantity: 0 item_total: '0.0' display_item_total: "$0.00" adjustment_total: '0.0' display_adjustment_total: "$0.00" discount_total: '0.0' display_discount_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" total: '0.0' display_total: "$0.00" gift_card_total: '0.0' display_gift_card_total: "$0.00" amount_due: '0.0' display_amount_due: "$0.00" delivery_total: '0.0' display_delivery_total: "$0.00" fulfillment_status: payment_status: completed_at: store_credit_total: '0.0' display_store_credit_total: "$0.00" covered_by_store_credit: false gift_card: market: status: draft last_ip_address: considered_risky: false confirmation_delivered: false store_owner_notification_delivered: payment_total: '0.0' display_payment_total: "$0.00" metadata: {} canceled_at: approved_at: created_at: '2026-06-12T17:24:46.324Z' updated_at: '2026-06-12T17:24:46.625Z' preferred_stock_location_id: tags: [] internal_note: approver_id: canceler_id: created_by_id: customer_id: cus_UkLWZg9DAJ requestBody: content: application/json: schema: type: object properties: email: type: string special_instructions: type: string internal_note: type: string channel_id: type: string description: Channel ID preferred_stock_location_id: type: string description: Stock Location ID to prefer for fulfillment. Re-runs Order Routing's PreferredLocation rule on subsequent shipment rebuilds. ship_address: type: object properties: firstname: type: string lastname: type: string address1: type: string city: type: string zipcode: type: string country_iso: type: string state_abbr: type: string phone: type: string bill_address: type: object properties: firstname: type: string lastname: type: string address1: type: string city: type: string zipcode: type: string country_iso: type: string state_abbr: type: string phone: type: string items: type: array items: type: object required: - variant_id properties: variant_id: type: string description: Variant ID quantity: type: integer example: 1 metadata: type: object delete: summary: Delete a draft order tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Deletes a draft order. Completed orders cannot be deleted. **Required scope:** `write_orders` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.orders.delete('or_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: id in: path required: true description: Order ID schema: type: string responses: '204': description: order deleted "/api/v3/admin/orders/{id}/complete": patch: summary: Complete an order tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Completes an order in the `confirm` state, marking it as placed. Set `notify_customer: true` to send the order confirmation email. **Required scope:** `write_orders` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const order = await client.orders.complete('or_UkLWZg9DAJ', { notify_customer: true, }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: id in: path required: true description: Order ID schema: type: string responses: '200': description: order completed content: application/json: example: id: or_UkLWZg9DAJ market_id: channel_id: ch_UkLWZg9DAJ number: R858666014 email: percy.nitzsche@vonrueden.us customer_note: currency: USD locale: en total_quantity: 1 item_total: '10.0' display_item_total: "$10.00" adjustment_total: '0.0' display_adjustment_total: "$0.00" discount_total: '0.0' display_discount_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" total: '110.0' display_total: "$110.00" gift_card_total: '0.0' display_gift_card_total: "$0.00" amount_due: '0.0' display_amount_due: "$0.00" delivery_total: '100.0' display_delivery_total: "$100.00" fulfillment_status: ready payment_status: paid completed_at: '2026-06-12T17:24:47.655Z' store_credit_total: '0.0' display_store_credit_total: "$0.00" covered_by_store_credit: false gift_card: market: status: draft last_ip_address: considered_risky: false confirmation_delivered: false store_owner_notification_delivered: payment_total: '110.0' display_payment_total: "$110.00" metadata: {} canceled_at: approved_at: created_at: '2026-06-12T17:24:47.569Z' updated_at: '2026-06-12T17:24:47.707Z' preferred_stock_location_id: tags: [] internal_note: approver_id: canceler_id: created_by_id: customer_id: cus_UkLWZg9DAJ '422': description: order cannot be completed content: application/json: example: error: code: order_cannot_complete message: No payment found details: base: - No payment found schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: notify_customer: type: boolean description: Send the order confirmation email after completion. "/api/v3/admin/orders/{id}/cancel": patch: summary: Cancel an order tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Cancels a completed order. **Required scope:** `write_orders` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const order = await client.orders.cancel('or_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: id in: path required: true description: Order ID schema: type: string responses: '200': description: order canceled content: application/json: example: id: or_UkLWZg9DAJ market_id: channel_id: ch_UkLWZg9DAJ number: R332298067 email: floria.harris@hagenes.name customer_note: currency: USD locale: en total_quantity: 1 item_total: '10.0' display_item_total: "$10.00" adjustment_total: '0.0' display_adjustment_total: "$0.00" discount_total: '0.0' display_discount_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" total: '20.0' display_total: "$20.00" gift_card_total: '0.0' display_gift_card_total: "$0.00" amount_due: "-0.0" display_amount_due: "$0.00" delivery_total: '10.0' display_delivery_total: "$10.00" fulfillment_status: canceled payment_status: void completed_at: '2026-06-12T17:24:49.066Z' store_credit_total: '0.0' display_store_credit_total: "$0.00" covered_by_store_credit: false gift_card: market: status: canceled last_ip_address: considered_risky: false confirmation_delivered: false store_owner_notification_delivered: payment_total: '0.0' display_payment_total: "$0.00" metadata: {} canceled_at: '2026-06-12T17:24:49.365Z' approved_at: created_at: '2026-06-12T17:24:49.003Z' updated_at: '2026-06-12T17:24:49.416Z' preferred_stock_location_id: tags: [] internal_note: approver_id: canceler_id: admin_UkLWZg9DAJ created_by_id: customer_id: cus_UkLWZg9DAJ "/api/v3/admin/orders/{id}/approve": patch: summary: Approve an order tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Approves an order (e.g., for fraud review). **Required scope:** `write_orders` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const order = await client.orders.approve('or_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: id in: path required: true description: Order ID schema: type: string responses: '200': description: order approved content: application/json: example: id: or_UkLWZg9DAJ market_id: channel_id: ch_UkLWZg9DAJ number: R700530633 email: coleen_hahn@kozey.us customer_note: currency: USD locale: en total_quantity: 1 item_total: '10.0' display_item_total: "$10.00" adjustment_total: '0.0' display_adjustment_total: "$0.00" discount_total: '0.0' display_discount_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" total: '110.0' display_total: "$110.00" gift_card_total: '0.0' display_gift_card_total: "$0.00" amount_due: '110.0' display_amount_due: "$110.00" delivery_total: '100.0' display_delivery_total: "$100.00" fulfillment_status: payment_status: completed_at: '2026-06-12T17:24:49.783Z' store_credit_total: '0.0' display_store_credit_total: "$0.00" covered_by_store_credit: false gift_card: market: status: draft last_ip_address: considered_risky: false confirmation_delivered: false store_owner_notification_delivered: payment_total: '0.0' display_payment_total: "$0.00" metadata: {} canceled_at: approved_at: '2026-06-12T17:24:50.082Z' created_at: '2026-06-12T17:24:49.725Z' updated_at: '2026-06-12T17:24:49.783Z' preferred_stock_location_id: tags: [] internal_note: approver_id: admin_UkLWZg9DAJ canceler_id: created_by_id: customer_id: cus_UkLWZg9DAJ "/api/v3/admin/orders/{id}/resume": patch: summary: Resume a canceled order tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Resumes a previously canceled order. **Required scope:** `write_orders` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const order = await client.orders.resume('or_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: id in: path required: true description: Order ID schema: type: string responses: '200': description: order resumed content: application/json: example: id: or_UkLWZg9DAJ market_id: channel_id: ch_UkLWZg9DAJ number: R883442430 email: cameron_hegmann@orn.ca customer_note: currency: USD locale: en total_quantity: 1 item_total: '10.0' display_item_total: "$10.00" adjustment_total: '0.0' display_adjustment_total: "$0.00" discount_total: '0.0' display_discount_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" total: '20.0' display_total: "$20.00" gift_card_total: '0.0' display_gift_card_total: "$0.00" amount_due: '20.0' display_amount_due: "$20.00" delivery_total: '10.0' display_delivery_total: "$10.00" fulfillment_status: canceled payment_status: void completed_at: '2026-06-12T17:24:50.441Z' store_credit_total: '0.0' display_store_credit_total: "$0.00" covered_by_store_credit: false gift_card: market: status: placed last_ip_address: considered_risky: false confirmation_delivered: false store_owner_notification_delivered: payment_total: '0.0' display_payment_total: "$0.00" metadata: {} canceled_at: '2026-06-12T17:24:50.726Z' approved_at: created_at: '2026-06-12T17:24:50.376Z' updated_at: '2026-06-12T17:24:50.822Z' preferred_stock_location_id: tags: [] internal_note: approver_id: canceler_id: admin_UkLWZg9DAJ created_by_id: customer_id: cus_UkLWZg9DAJ "/api/v3/admin/orders/{id}/resend_confirmation": post: summary: Resend confirmation email tags: - Orders security: - api_key: [] bearer_auth: [] description: |- Publishes the order.completed event to trigger confirmation email delivery. **Required scope:** `write_orders` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.orders.resendConfirmation('or_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: id in: path required: true description: Order ID schema: type: string responses: '200': description: confirmation resent content: application/json: example: id: or_UkLWZg9DAJ market_id: channel_id: ch_UkLWZg9DAJ number: R467281645 email: tyra_barton@hessel.biz customer_note: currency: USD locale: en total_quantity: 1 item_total: '10.0' display_item_total: "$10.00" adjustment_total: '0.0' display_adjustment_total: "$0.00" discount_total: '0.0' display_discount_total: "$0.00" tax_total: '0.0' display_tax_total: "$0.00" included_tax_total: '0.0' display_included_tax_total: "$0.00" additional_tax_total: '0.0' display_additional_tax_total: "$0.00" total: '110.0' display_total: "$110.00" gift_card_total: '0.0' display_gift_card_total: "$0.00" amount_due: '110.0' display_amount_due: "$110.00" delivery_total: '100.0' display_delivery_total: "$100.00" fulfillment_status: payment_status: completed_at: '2026-06-12T17:24:51.184Z' store_credit_total: '0.0' display_store_credit_total: "$0.00" covered_by_store_credit: false gift_card: market: status: draft last_ip_address: considered_risky: false confirmation_delivered: false store_owner_notification_delivered: payment_total: '0.0' display_payment_total: "$0.00" metadata: {} canceled_at: approved_at: created_at: '2026-06-12T17:24:51.117Z' updated_at: '2026-06-12T17:24:51.184Z' preferred_stock_location_id: tags: [] internal_note: approver_id: canceler_id: created_by_id: customer_id: cus_UkLWZg9DAJ "/api/v3/admin/payment_methods": get: summary: List payment methods tags: - Payment Methods security: - api_key: [] bearer_auth: [] description: |- Returns the store's configured payment methods. Use `source_required: true` to know which methods need a saved source. **Required scope:** `read_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: paymentMethods } = await client.paymentMethods.list() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand. Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., name,type,active). id is always included. schema: type: string responses: '200': description: payment methods found content: application/json: example: data: - id: pm_UkLWZg9DAJ name: Check description: type: check session_required: false source_required: false metadata: {} active: true auto_capture: storefront_visible: true position: 1 created_at: '2026-06-12T17:24:51.507Z' updated_at: '2026-06-12T17:24:51.509Z' preferences: {} preference_schema: [] meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: "/api/v3/admin/payment_methods/types": get: summary: List available payment provider types tags: - Payment Methods security: - api_key: [] bearer_auth: [] description: |- Returns the registered Spree::PaymentMethod subclasses that can be used to create new payment methods. Useful for populating a "Provider" dropdown in admin UIs. **Required scope:** `read_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: types } = await client.paymentMethods.types() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: provider types found content: application/json: example: data: - type: bogus label: Bogus description: preference_schema: - key: dummy_secret_key type: password default: - key: dummy_key type: string default: PUBLICKEY123 - type: custom_payment_source_method label: Custom Payment Source Method description: preference_schema: [] "/api/v3/admin/payment_methods/{id}": get: summary: Show a payment method tags: - Payment Methods security: - api_key: [] bearer_auth: [] description: |- Returns a payment method by ID. **Required scope:** `read_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const paymentMethod = await client.paymentMethods.get('pm_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand. Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., name,type,active). id is always included. schema: type: string responses: '200': description: payment method found content: application/json: example: id: pm_UkLWZg9DAJ name: Check description: type: check session_required: false source_required: false metadata: {} active: true auto_capture: storefront_visible: true position: 1 created_at: '2026-06-12T17:24:52.124Z' updated_at: '2026-06-12T17:24:52.126Z' preferences: {} preference_schema: [] "/api/v3/admin/orders/{order_id}/payments": get: summary: List payments tags: - Payments security: - api_key: [] bearer_auth: [] description: |- Returns all payments for an order. **Required scope:** `read_payments` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: payments } = await client.orders.payments.list('or_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., payment_method, source). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., amount,status,number,response_code). id is always included. schema: type: string responses: '200': description: payments found content: application/json: example: data: - id: py_UkLWZg9DAJ payment_method_id: pm_UkLWZg9DAJ response_code: BGS-666a0970d255 number: PST3ZPXJ amount: '110.0' display_amount: "$110.00" status: completed source_type: credit_card source_id: card_UkLWZg9DAJ source: id: card_UkLWZg9DAJ brand: visa last4: '1111' month: 12 year: 2027 name: Spree Commerce default: false gateway_payment_profile_id: customer_id: payment_method_id: pm_gbHJdmfrXB metadata: {} created_at: '2026-06-12T17:24:35.003Z' updated_at: '2026-06-12T17:24:35.006Z' metadata: {} avs_response: cvv_response_code: cvv_response_message: created_at: '2026-06-12T17:24:35.005Z' updated_at: '2026-06-12T17:24:35.005Z' captured_amount: '0.0' order_id: or_UkLWZg9DAJ meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: post: summary: Create a payment tags: - Payments security: - api_key: [] bearer_auth: [] description: |- Creates a new payment for the order. **Required scope:** `write_payments` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const payment = await client.orders.payments.create('or_UkLWZg9DAJ', { payment_method_id: 'pm_UkLWZg9DAJ', amount: 99.99, source_id: 'cc_UkLWZg9DAJ', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string responses: '201': description: payment created content: application/json: example: id: py_gbHJdmfrXB payment_method_id: pm_EfhxLZ9ck8 response_code: number: PRZAZQJ8 amount: '110.0' display_amount: "$110.00" status: checkout source_type: source_id: source: metadata: {} avs_response: cvv_response_code: cvv_response_message: created_at: '2026-06-12T17:24:36.354Z' updated_at: '2026-06-12T17:24:36.354Z' captured_amount: '0.0' order_id: or_gbHJdmfrXB requestBody: content: application/json: schema: type: object required: - payment_method_id properties: payment_method_id: type: string description: Payment method ID amount: type: number example: 99.99 source_id: type: string description: Payment source ID "/api/v3/admin/orders/{order_id}/payments/{id}": get: summary: Show a payment tags: - Payments security: - api_key: [] bearer_auth: [] description: |- Returns details of a specific payment. **Required scope:** `read_payments` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const payment = await client.orders.payments.get('or_UkLWZg9DAJ', 'pay_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: id in: path required: true description: Payment ID schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., payment_method, source). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., amount,status,number,response_code). id is always included. schema: type: string responses: '200': description: payment found content: application/json: example: id: py_UkLWZg9DAJ payment_method_id: pm_UkLWZg9DAJ response_code: BGS-67d8bd9175fb number: PFKTQFMQ amount: '110.0' display_amount: "$110.00" status: completed source_type: credit_card source_id: card_UkLWZg9DAJ source: id: card_UkLWZg9DAJ brand: visa last4: '1111' month: 12 year: 2027 name: Spree Commerce default: false gateway_payment_profile_id: customer_id: payment_method_id: pm_gbHJdmfrXB metadata: {} created_at: '2026-06-12T17:24:36.816Z' updated_at: '2026-06-12T17:24:36.820Z' metadata: {} avs_response: cvv_response_code: cvv_response_message: created_at: '2026-06-12T17:24:36.819Z' updated_at: '2026-06-12T17:24:36.819Z' captured_amount: '0.0' order_id: or_UkLWZg9DAJ "/api/v3/admin/orders/{order_id}/payments/{id}/capture": patch: summary: Capture a payment tags: - Payments security: - api_key: [] bearer_auth: [] description: |- Captures a pending payment. **Required scope:** `write_payments` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const payment = await client.orders.payments.capture('or_UkLWZg9DAJ', 'pay_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: id in: path required: true description: Payment ID schema: type: string responses: '200': description: payment captured content: application/json: example: id: py_UkLWZg9DAJ payment_method_id: pm_UkLWZg9DAJ response_code: BGS-b63164b5fd08 number: PV70TAWA amount: '110.0' display_amount: "$110.00" status: completed source_type: credit_card source_id: card_UkLWZg9DAJ source: id: card_UkLWZg9DAJ brand: visa last4: '1111' month: 12 year: 2027 name: Spree Commerce default: false gateway_payment_profile_id: customer_id: payment_method_id: pm_gbHJdmfrXB metadata: {} created_at: '2026-06-12T17:24:37.491Z' updated_at: '2026-06-12T17:24:37.494Z' metadata: {} avs_response: cvv_response_code: cvv_response_message: created_at: '2026-06-12T17:24:37.493Z' updated_at: '2026-06-12T17:24:37.844Z' captured_amount: '110.0' order_id: or_UkLWZg9DAJ '422': description: capture failed content: application/json: example: error: code: processing_error message: 'Bogus Gateway: Forced failure' schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v3/admin/orders/{order_id}/payments/{id}/void": patch: summary: Void a payment tags: - Payments security: - api_key: [] bearer_auth: [] description: |- Voids a payment. **Required scope:** `write_payments` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const payment = await client.orders.payments.void('or_UkLWZg9DAJ', 'pay_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: id in: path required: true description: Payment ID schema: type: string responses: '200': description: payment voided content: application/json: example: id: py_UkLWZg9DAJ payment_method_id: pm_UkLWZg9DAJ response_code: void-BGS-2993d99c08c2 number: PJKLS93Y amount: '110.0' display_amount: "$110.00" status: void source_type: credit_card source_id: card_UkLWZg9DAJ source: id: card_UkLWZg9DAJ brand: visa last4: '1111' month: 12 year: 2027 name: Spree Commerce default: false gateway_payment_profile_id: customer_id: payment_method_id: pm_gbHJdmfrXB metadata: {} created_at: '2026-06-12T17:24:38.988Z' updated_at: '2026-06-12T17:24:38.991Z' metadata: {} avs_response: cvv_response_code: cvv_response_message: created_at: '2026-06-12T17:24:38.990Z' updated_at: '2026-06-12T17:24:39.301Z' captured_amount: '0.0' order_id: or_UkLWZg9DAJ "/api/v3/admin/price_lists": get: summary: List price lists tags: - Pricing security: - api_key: [] bearer_auth: [] description: |- Returns the price lists configured for the current store. **Required scope:** `read_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: page in: query required: false schema: type: integer - name: limit in: query required: false schema: type: integer - name: q[name_cont] in: query required: false schema: type: string - name: q[status_eq] in: query required: false schema: type: string - name: sort in: query required: false schema: type: string - name: expand in: query required: false description: 'Comma-separated associations to embed. Supported: `price_rules`.' schema: type: string responses: '200': description: price lists found content: application/json: example: data: - id: pl_UkLWZg9DAJ name: Wholesale description: status: draft position: 1 match_policy: all starts_at: ends_at: deleted_at: created_at: '2026-06-12T17:24:52.444Z' updated_at: '2026-06-12T17:24:52.444Z' currently_active: false products_count: 0 prices_count: 0 product_ids: [] - id: pl_gbHJdmfrXB name: Holiday description: status: draft position: 2 match_policy: all starts_at: ends_at: deleted_at: created_at: '2026-06-12T17:24:52.447Z' updated_at: '2026-06-12T17:24:52.447Z' currently_active: false products_count: 0 prices_count: 0 product_ids: [] meta: page: 1 limit: 25 count: 2 pages: 1 from: 1 to: 2 in: 2 previous: next: schema: type: object properties: data: type: array items: "$ref": "#/components/schemas/PriceList" meta: "$ref": "#/components/schemas/PaginationMeta" required: - data - meta post: summary: Create a price list tags: - Pricing security: - api_key: [] bearer_auth: [] description: |- Creates a new draft price list. **Required scope:** `write_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '201': description: price list created (server-to-server — rules + prices, no product_ids) content: application/json: example: id: pl_EfhxLZ9ck8 name: EU wholesale description: status: draft position: 3 match_policy: all starts_at: ends_at: deleted_at: created_at: '2026-06-12T17:24:53.499Z' updated_at: '2026-06-12T17:24:53.501Z' currently_active: false products_count: 1 prices_count: 2 product_ids: - prod_UkLWZg9DAJ schema: "$ref": "#/components/schemas/PriceList" '422': description: validation error content: application/json: example: error: code: validation_error message: Name can't be blank details: name: - can't be blank schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object required: - name properties: name: type: string example: EU wholesale description: type: string nullable: true starts_at: type: string nullable: true example: '2026-06-01T00:00:00Z' ends_at: type: string nullable: true example: '2026-09-01T00:00:00Z' match_policy: type: string enum: - all - any example: all position: type: integer example: 1 product_ids: type: array items: type: string description: Prefixed product ids to seed the list with. example: - prod_aBc123 rules: type: array description: STI-typed price rules to attach on create. Existing rules on the same payload via PATCH reconcile by id. items: type: object required: - type properties: type: type: string example: volume_rule preferences: type: object additionalProperties: true prices: type: array description: 'Server-to-server alternative to `product_ids`: ship the exact per-variant prices the list should contain. Each row upserts on the unique key `(variant_id, currency, price_list_id)`. Mix-and-match with `product_ids` is supported but typically unnecessary — `prices` alone tells the server which variants belong to the list and what the override amount is.' items: type: object required: - variant_id - currency properties: variant_id: type: string example: variant_xY9 currency: type: string example: USD amount: type: string nullable: true example: '19.99' compare_at_amount: type: string nullable: true example: '24.99' "/api/v3/admin/price_lists/{id}": parameters: - name: id in: path required: true schema: type: string get: summary: Get a price list tags: - Pricing security: - api_key: [] bearer_auth: [] description: "**Required scope:** `read_products` (for API-key authentication)." parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: expand in: query required: false schema: type: string responses: '200': description: price list found content: application/json: example: id: pl_UkLWZg9DAJ name: Wholesale description: status: draft position: 1 match_policy: all starts_at: ends_at: deleted_at: created_at: '2026-06-12T17:24:53.806Z' updated_at: '2026-06-12T17:24:53.806Z' currently_active: false products_count: 0 prices_count: 0 product_ids: [] schema: "$ref": "#/components/schemas/PriceList" '404': description: price list not found content: application/json: example: error: code: record_not_found message: Price list not found schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update a price list tags: - Pricing security: - api_key: [] bearer_auth: [] description: |- Updates a price list. The optional `rules:` array reconciles nested STI-typed price rules in a single round-trip — existing rules update by `id`, new rules build, missing rules destroy. Mirrors the promotion editor's "save the whole thing on Save" pattern. **Required scope:** `write_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: price list updated with nested rules content: application/json: example: id: pl_UkLWZg9DAJ name: Wholesale (Q3) description: status: draft position: 1 match_policy: all starts_at: ends_at: deleted_at: created_at: '2026-06-12T17:24:55.427Z' updated_at: '2026-06-12T17:24:55.712Z' currently_active: false products_count: 0 prices_count: 0 product_ids: [] schema: "$ref": "#/components/schemas/PriceList" requestBody: content: application/json: schema: type: object properties: name: type: string description: type: string nullable: true starts_at: type: string nullable: true ends_at: type: string nullable: true match_policy: type: string enum: - all - any position: type: integer product_ids: type: array items: type: string description: Prefixed product ids — reconciles list membership (adds + removes). example: - prod_aBc123 rules: type: array items: type: object required: - type properties: id: type: string nullable: true type: type: string example: volume_rule preferences: type: object additionalProperties: true prices: type: array description: Individual price overrides (the spreadsheet payload). Each row updates by `id` if shipped, otherwise upserts on the unique key `(variant_id, currency, price_list_id)`. items: type: object oneOf: - required: - id - required: - variant_id - currency properties: id: type: string example: price_aBc123 variant_id: type: string example: variant_xY9 currency: type: string example: USD amount: type: string nullable: true example: '12.50' compare_at_amount: type: string nullable: true example: '15.00' delete: summary: Delete a price list tags: - Pricing security: - api_key: [] bearer_auth: [] description: |- Soft-deletes the price list. Associated prices are removed asynchronously. **Required scope:** `write_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '204': description: price list deleted "/api/v3/admin/price_lists/{id}/activate": parameters: - name: id in: path required: true schema: type: string patch: summary: Activate a price list tags: - Pricing security: - api_key: [] bearer_auth: [] description: |- Transitions a draft / inactive list to `active`. If `starts_at` is in the future the list is marked `scheduled` instead, matching the legacy admin behaviour. **Required scope:** `write_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: price list activated content: application/json: example: id: pl_UkLWZg9DAJ name: Wholesale description: status: active position: 1 match_policy: all starts_at: ends_at: deleted_at: created_at: '2026-06-12T17:24:56.035Z' updated_at: '2026-06-12T17:24:56.320Z' currently_active: true products_count: 0 prices_count: 0 product_ids: [] schema: "$ref": "#/components/schemas/PriceList" "/api/v3/admin/price_lists/{id}/deactivate": parameters: - name: id in: path required: true schema: type: string patch: summary: Deactivate a price list tags: - Pricing security: - api_key: [] bearer_auth: [] description: "**Required scope:** `write_products` (for API-key authentication)." parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: price list deactivated content: application/json: example: id: pl_UkLWZg9DAJ name: Price List 1 description: status: inactive position: 1 match_policy: all starts_at: ends_at: deleted_at: created_at: '2026-06-12T17:24:56.329Z' updated_at: '2026-06-12T17:24:56.617Z' currently_active: false products_count: 0 prices_count: 0 product_ids: [] schema: "$ref": "#/components/schemas/PriceList" "/api/v3/admin/prices": get: summary: List prices tags: - Pricing security: - api_key: [] bearer_auth: [] description: |- Generic prices endpoint covering both base prices and price-list overrides. Filter with Ransack: `q[price_list_id_eq]=…`, `q[currency_eq]=USD`, `q[price_list_id_null]=true` (base prices only). The admin spreadsheet uses this with server-side pagination so it scales past the metadata-PATCH path on `/price_lists/:id`. **Required scope:** `read_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: prices } = await client.prices.list({ price_list_id_eq: 'pl_xxx', currency_eq: 'USD', expand: ['variant'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: page in: query required: false schema: type: integer - name: limit in: query required: false schema: type: integer - name: q[price_list_id_eq] in: query required: false schema: type: string - name: q[price_list_id_null] in: query required: false schema: type: boolean - name: q[currency_eq] in: query required: false schema: type: string - name: q[variant_id_eq] in: query required: false schema: type: string - name: sort in: query required: false description: Comma-separated sort keys. Supports e.g. `variant_product_name,variant_id`. schema: type: string - name: expand in: query required: false description: 'Comma-separated associations to embed. Supported: `variant`.' schema: type: string responses: '200': description: prices found content: application/json: example: data: - id: price_gbHJdmfrXB amount: '19.99' amount_in_cents: 1999 compare_at_amount: compare_at_amount_in_cents: currency: USD display_amount: "$19.99" display_compare_at_amount: price_list_id: variant_id: variant_gbHJdmfrXB created_at: '2026-06-12T17:24:56.681Z' updated_at: '2026-06-12T17:24:56.681Z' - id: price_EfhxLZ9ck8 amount: '5.0' amount_in_cents: 500 compare_at_amount: compare_at_amount_in_cents: currency: USD display_amount: "$5.00" display_compare_at_amount: price_list_id: pl_UkLWZg9DAJ variant_id: variant_gbHJdmfrXB created_at: '2026-06-12T17:24:56.685Z' updated_at: '2026-06-12T17:24:56.685Z' meta: page: 1 limit: 25 count: 2 pages: 1 from: 1 to: 2 in: 2 previous: next: schema: type: object properties: data: type: array items: "$ref": "#/components/schemas/Price" meta: "$ref": "#/components/schemas/PaginationMeta" required: - data - meta post: summary: Create a price tags: - Pricing security: - api_key: [] bearer_auth: [] description: |- Creates a single price. Omit `price_list_id` to create a base price. For more than a handful of rows, prefer `POST /admin/prices/bulk_upsert`. **Required scope:** `write_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const price = await client.prices.create({ variant_id: 'variant_xxx', currency: 'USD', amount: '19.99', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '201': description: price created content: application/json: example: id: price_uw2YK1rnl0 amount: '9.99' amount_in_cents: 999 compare_at_amount: compare_at_amount_in_cents: currency: EUR display_amount: "€9.99" display_compare_at_amount: price_list_id: variant_id: variant_EfhxLZ9ck8 created_at: '2026-06-12T17:24:57.494Z' updated_at: '2026-06-12T17:24:57.494Z' schema: "$ref": "#/components/schemas/Price" requestBody: content: application/json: schema: type: object required: - variant_id - currency properties: variant_id: type: string example: variant_xY9 currency: type: string example: USD amount: type: string nullable: true example: '19.99' compare_at_amount: type: string nullable: true example: '24.99' price_list_id: type: string nullable: true example: pl_aBc123 "/api/v3/admin/prices/{id}": parameters: - name: id in: path required: true schema: type: string get: summary: Get a price tags: - Pricing security: - api_key: [] bearer_auth: [] description: "**Required scope:** `read_products` (for API-key authentication)." x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const price = await client.prices.get('price_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: price found content: application/json: example: id: price_EfhxLZ9ck8 amount: '5.0' amount_in_cents: 500 compare_at_amount: compare_at_amount_in_cents: currency: USD display_amount: "$5.00" display_compare_at_amount: price_list_id: pl_UkLWZg9DAJ variant_id: variant_gbHJdmfrXB created_at: '2026-06-12T17:24:57.574Z' updated_at: '2026-06-12T17:24:57.574Z' schema: "$ref": "#/components/schemas/Price" '404': description: price not found content: application/json: example: error: code: record_not_found message: Price not found schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update a price tags: - Pricing security: - api_key: [] bearer_auth: [] description: "**Required scope:** `write_products` (for API-key authentication)." x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const price = await client.prices.update('price_xxx', { amount: '12.34', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: price updated content: application/json: example: id: price_EfhxLZ9ck8 amount: '12.34' amount_in_cents: 1234 compare_at_amount: compare_at_amount_in_cents: currency: USD display_amount: "$12.34" display_compare_at_amount: price_list_id: pl_UkLWZg9DAJ variant_id: variant_gbHJdmfrXB created_at: '2026-06-12T17:24:58.283Z' updated_at: '2026-06-12T17:24:58.593Z' schema: "$ref": "#/components/schemas/Price" requestBody: content: application/json: schema: type: object properties: amount: type: string nullable: true compare_at_amount: type: string nullable: true delete: summary: Delete a price tags: - Pricing security: - api_key: [] bearer_auth: [] description: |- Soft-deletes the price (acts_as_paranoid). **Required scope:** `write_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.prices.delete('price_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '204': description: price deleted "/api/v3/admin/prices/bulk_upsert": post: summary: Bulk-upsert prices tags: - Pricing security: - api_key: [] bearer_auth: [] description: |- Upserts a batch of prices in a single SQL round trip. Each row either: * targets an existing price by `id`, OR * matches on the unique key `(variant_id, currency, price_list_id)` — updating the existing row if one exists, creating one otherwise. Model callbacks (e.g. PriceHistory) are bypassed; this is a bulk-write fast path for the admin spreadsheet. The response carries `price_count` — the number of rows touched. **Required scope:** `write_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { price_count } = await client.prices.bulkUpsert({ prices: [ { variant_id: 'variant_xxx', currency: 'USD', price_list_id: 'pl_xxx', amount: '11.11', }, { variant_id: 'variant_yyy', currency: 'USD', price_list_id: 'pl_xxx', amount: '22.22', }, ], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: prices upserted content: application/json: example: price_count: 2 schema: type: object properties: price_count: type: integer '422': description: missing prices key content: application/json: example: error: code: missing_prices message: prices is required (send an empty array to no-op). schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object required: - prices properties: prices: type: array items: type: object required: - variant_id - currency properties: id: type: string nullable: true example: price_aBc123 variant_id: type: string example: variant_xY9 currency: type: string example: USD price_list_id: type: string nullable: true example: pl_aBc123 amount: type: string nullable: true example: '19.99' compare_at_amount: type: string nullable: true example: '24.99' "/api/v3/admin/prices/bulk_destroy": delete: summary: Bulk-delete prices tags: - Pricing security: - api_key: [] bearer_auth: [] description: |- Soft-deletes each price in `ids`. Returns the count actually destroyed. **Required scope:** `write_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { price_count } = await client.prices.bulkDestroy({ ids: ['price_xxx', 'price_yyy'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: prices deleted content: application/json: example: price_count: 1 schema: type: object properties: price_count: type: integer requestBody: content: application/json: schema: type: object required: - ids properties: ids: type: array items: type: string "/api/v3/admin/products/{product_id}/custom_fields": get: summary: List product custom fields tags: - Products security: - api_key: [] bearer_auth: [] description: |- Returns the product's custom field values. **Required scope:** `read_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: customFields } = await client.products.customFields.list('prod_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: product_id in: path required: true schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., custom_field_definition). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., key,value,namespace). id is always included. schema: type: string responses: '200': description: custom fields found content: application/json: example: data: - id: cf_UkLWZg9DAJ label: Title type: Spree::Metafields::ShortText field_type: short_text key: custom.title value: wool created_at: '2026-06-12T17:25:00.143Z' updated_at: '2026-06-12T17:25:00.143Z' storefront_visible: true custom_field_definition_id: cfdef_UkLWZg9DAJ meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: post: summary: Create a product custom field tags: - Products security: - api_key: [] bearer_auth: [] description: |- Sets a custom field value on the product. Requires an existing CustomFieldDefinition; pass its prefixed `cfdef_…` id. **Required scope:** `write_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const customField = await client.products.customFields.create('prod_UkLWZg9DAJ', { custom_field_definition_id: 'cfdef_AbC123XyZ', value: 'wool', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: product_id in: path required: true schema: type: string responses: '201': description: custom field created content: application/json: example: id: cf_gbHJdmfrXB label: Description type: Spree::Metafields::LongText field_type: long_text key: custom.description value: A longer description created_at: '2026-06-12T17:25:00.791Z' updated_at: '2026-06-12T17:25:00.791Z' storefront_visible: true custom_field_definition_id: cfdef_gbHJdmfrXB '422': description: duplicate definition for the same product content: application/json: example: error: code: validation_error message: Metafield definition has already been taken details: metafield_definition_id: - has already been taken requestBody: content: application/json: schema: type: object required: - custom_field_definition_id - value properties: custom_field_definition_id: type: string description: Prefixed `cfdef_…` id value: description: Value matching the definition's `field_type` "/api/v3/admin/products/{product_id}/custom_fields/{id}": get: summary: Show a product custom field tags: - Products security: - api_key: [] bearer_auth: [] description: "**Required scope:** `read_products` (for API-key authentication)." parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: product_id in: path required: true schema: type: string - name: id in: path required: true schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., custom_field_definition). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., key,value,namespace). id is always included. schema: type: string responses: '200': description: custom field found content: application/json: example: id: cf_UkLWZg9DAJ label: Title type: Spree::Metafields::ShortText field_type: short_text key: custom.title value: wool created_at: '2026-06-12T17:25:01.167Z' updated_at: '2026-06-12T17:25:01.167Z' storefront_visible: true custom_field_definition_id: cfdef_UkLWZg9DAJ patch: summary: Update a product custom field tags: - Products security: - api_key: [] bearer_auth: [] description: |- Updates the custom field's `value`. The linked definition cannot be changed — delete and recreate to switch. **Required scope:** `write_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: product_id in: path required: true schema: type: string - name: id in: path required: true schema: type: string responses: '200': description: custom field updated content: application/json: example: id: cf_UkLWZg9DAJ label: Title type: Spree::Metafields::ShortText field_type: short_text key: custom.title value: cotton created_at: '2026-06-12T17:25:01.494Z' updated_at: '2026-06-12T17:25:01.792Z' storefront_visible: true custom_field_definition_id: cfdef_UkLWZg9DAJ requestBody: content: application/json: schema: type: object required: - value properties: value: description: New value delete: summary: Delete a product custom field tags: - Products security: - api_key: [] bearer_auth: [] description: "**Required scope:** `write_products` (for API-key authentication)." parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: product_id in: path required: true schema: type: string - name: id in: path required: true schema: type: string responses: '204': description: custom field deleted "/api/v3/admin/products": get: summary: List products tags: - Products security: - api_key: [] bearer_auth: [] description: |- Returns a paginated list of products for the current store. **Required scope:** `read_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: products } = await client.products.list({ name_cont: 'shirt', status_eq: 'active', sort: '-created_at', limit: 25, }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: page in: query required: false description: Page number schema: type: integer - name: limit in: query required: false description: Number of records per page schema: type: integer - name: sort in: query required: false description: Sort field (e.g., name, -name, price, -price, best_selling) schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., variants, media, option_types, categories). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., name,slug,price,status). id is always included. schema: type: string - name: q[name_cont] in: query required: false description: Filter by name (contains) schema: type: string - name: q[status_eq] in: query required: false description: Filter by status schema: type: string responses: '200': description: products found content: application/json: example: data: - id: prod_UkLWZg9DAJ name: Product 572113 slug: product-572113 meta_title: meta_description: meta_keywords: variant_count: 0 available_on: purchasable: true in_stock: false backorderable: true available: true description: Optio eum culpa id nostrum aspernatur tenetur asperiores. Qui quos quod laudantium tempora sequi. Adipisci sequi neque commodi tenetur. Veritatis doloremque fugiat quae accusantium inventore perferendis provident laudantium. Similique officiis quasi saepe reiciendis quam molestias. description_html: Optio eum culpa id nostrum aspernatur tenetur asperiores. Qui quos quod laudantium tempora sequi. Adipisci sequi neque commodi tenetur. Veritatis doloremque fugiat quae accusantium inventore perferendis provident laudantium. Similique officiis quasi saepe reiciendis quam molestias. default_variant_id: variant_UkLWZg9DAJ thumbnail_url: tags: [] price: id: price_UkLWZg9DAJ amount: '19.99' amount_in_cents: 1999 compare_at_amount: compare_at_amount_in_cents: currency: USD display_amount: "$19.99" display_compare_at_amount: price_list_id: variant_id: variant_UkLWZg9DAJ created_at: '2026-06-12T17:25:02.180Z' updated_at: '2026-06-12T17:25:02.180Z' original_price: status: active metadata: {} deleted_at: created_at: '2026-06-12T17:25:02.168Z' updated_at: '2026-06-12T17:25:02.188Z' tax_category_id: taxcat_UkLWZg9DAJ meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: schema: type: object properties: data: type: array items: "$ref": "#/components/schemas/Product" meta: "$ref": "#/components/schemas/PaginationMeta" required: - data - meta '401': description: unauthorized content: application/json: example: error: code: authentication_required message: Authentication required schema: "$ref": "#/components/schemas/ErrorResponse" post: summary: Create a product tags: - Products security: - api_key: [] bearer_auth: [] description: |- Creates a new product. Supports nested variants with prices and option types. Option types and values are auto-created if they don't exist. Prices are upserted by currency. Stock items are upserted by stock location. **Required scope:** `write_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const product = await client.products.create({ name: 'Premium T-Shirt', description: 'Soft, organic cotton.', status: 'active', variants: [ { sku: 'TSHIRT-S-NAVY', options: [ { name: 'size', value: 'Small' }, { name: 'color', value: 'navy' }, ], prices: [ { currency: 'USD', amount: 29.99 }, { currency: 'EUR', amount: 27.99 }, ], stock_items: [ { stock_location_id: 'sloc_UkLWZg9DAJ', count_on_hand: 50 }, ], }, { sku: 'TSHIRT-M-NAVY', options: [ { name: 'size', value: 'Medium' }, { name: 'color', value: 'navy' }, ], prices: [{ currency: 'USD', amount: 29.99 }], stock_items: [ { stock_location_id: 'sloc_UkLWZg9DAJ', count_on_hand: 30 }, ], }, ], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '201': description: product created content: application/json: example: id: prod_gbHJdmfrXB name: New Product slug: new-product meta_title: meta_description: meta_keywords: variant_count: 0 available_on: purchasable: false in_stock: false backorderable: false available: false description: description_html: default_variant_id: variant_gbHJdmfrXB thumbnail_url: tags: [] price: original_price: status: draft metadata: {} deleted_at: created_at: '2026-06-12T17:25:02.877Z' updated_at: '2026-06-12T17:25:02.878Z' tax_category_id: schema: "$ref": "#/components/schemas/Product" '422': description: validation error content: application/json: example: error: code: validation_error message: Name can't be blank details: name: - can't be blank schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: name: type: string example: Premium T-Shirt description: type: string slug: type: string status: type: string enum: - draft - active - archived tax_category_id: type: string description: Tax category ID category_ids: type: array items: type: string description: Array of category IDs tags: type: array items: type: string example: - eco - sale variants: type: array description: Array of variant payloads. Variants can declare multiple option pairs via `options:` and per-currency prices via `prices:`. Stock counts go in `stock_items:` (per stock location). items: type: object properties: sku: type: string options: type: array description: One pair per option type the variant participates in (e.g. size + color). Option types and values are auto-created if missing. items: type: object required: - name - value properties: name: type: string example: size value: type: string example: Small prices: type: array description: Per-currency prices. Upserted by currency. items: type: object required: - currency - amount properties: currency: type: string example: USD amount: type: number example: 29.99 compare_at_amount: type: number example: 39.99 stock_items: type: array description: Per-stock-location inventory. Upserted by stock_location_id. items: type: object required: - stock_location_id - count_on_hand properties: stock_location_id: type: string description: Stock location ID (e.g. sloc_xxx) count_on_hand: type: integer example: 50 backorderable: type: boolean required: - name "/api/v3/admin/products/{id}": get: summary: Get a product tags: - Products security: - api_key: [] bearer_auth: [] description: |- Returns a single product by ID. **Required scope:** `read_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const product = await client.products.get('prod_86Rf07xd4z', { expand: ['variants', 'option_types'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: id in: path required: true description: Product ID (e.g., prod_xxx) schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., variants, media, option_types, categories). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., name,slug,price,status). id is always included. schema: type: string responses: '200': description: product found content: application/json: example: id: prod_UkLWZg9DAJ name: Product 61236 slug: product-61236 meta_title: meta_description: meta_keywords: variant_count: 0 available_on: purchasable: true in_stock: false backorderable: true available: true description: Minima nisi impedit aut sed aspernatur repellendus ullam quisquam. Quod ab vero occaecati quasi. Quasi in tempore iure aut praesentium reprehenderit repellat. Voluptatem fugit eius natus quisquam rerum animi placeat cumque. Pariatur quaerat porro possimus animi at facere eaque. Molestias accusamus neque officiis ut aspernatur totam saepe. Debitis at voluptatibus libero ducimus totam non asperiores reprehenderit. Veritatis eos iusto quis sapiente magnam. Dignissimos inventore quo et ipsam reprehenderit praesentium vitae minima. Inventore eaque praesentium earum ipsam consequatur. Corporis voluptatem iure ipsam iste perferendis quaerat at sit. Nesciunt laudantium itaque necessitatibus possimus provident enim quos. Aperiam a quis aliquam quas necessitatibus eos ut fuga. Quaerat labore nobis animi molestiae. Consequuntur rem molestias distinctio ipsa. description_html: |- Minima nisi impedit aut sed aspernatur repellendus ullam quisquam. Quod ab vero occaecati quasi. Quasi in tempore iure aut praesentium reprehenderit repellat. Voluptatem fugit eius natus quisquam rerum animi placeat cumque. Pariatur quaerat porro possimus animi at facere eaque. Molestias accusamus neque officiis ut aspernatur totam saepe. Debitis at voluptatibus libero ducimus totam non asperiores reprehenderit. Veritatis eos iusto quis sapiente magnam. Dignissimos inventore quo et ipsam reprehenderit praesentium vitae minima. Inventore eaque praesentium earum ipsam consequatur. Corporis voluptatem iure ipsam iste perferendis quaerat at sit. Nesciunt laudantium itaque necessitatibus possimus provident enim quos. Aperiam a quis aliquam quas necessitatibus eos ut fuga. Quaerat labore nobis animi molestiae. Consequuntur rem molestias distinctio ipsa. default_variant_id: variant_UkLWZg9DAJ thumbnail_url: tags: [] price: id: price_UkLWZg9DAJ amount: '19.99' amount_in_cents: 1999 compare_at_amount: compare_at_amount_in_cents: currency: USD display_amount: "$19.99" display_compare_at_amount: price_list_id: variant_id: variant_UkLWZg9DAJ created_at: '2026-06-12T17:25:03.263Z' updated_at: '2026-06-12T17:25:03.263Z' original_price: status: active metadata: {} deleted_at: created_at: '2026-06-12T17:25:03.252Z' updated_at: '2026-06-12T17:25:03.269Z' tax_category_id: taxcat_UkLWZg9DAJ schema: "$ref": "#/components/schemas/Product" '404': description: product not found content: application/json: example: error: code: record_not_found message: Product not found schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update a product tags: - Products security: - api_key: [] bearer_auth: [] description: |- Updates a product. Only provided fields are updated. **Required scope:** `write_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const product = await client.products.update('prod_86Rf07xd4z', { name: 'Updated Name', status: 'active', tags: ['eco', 'sale'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: id in: path required: true description: Product ID schema: type: string responses: '200': description: product updated content: application/json: example: id: prod_UkLWZg9DAJ name: Updated Name slug: product-637715 meta_title: meta_description: meta_keywords: variant_count: 0 available_on: purchasable: true in_stock: false backorderable: true available: true description: Minima esse id porro impedit aliquid quam sint. Vero exercitationem voluptate consequatur fuga eos dolorum corrupti recusandae. Non similique facere beatae repudiandae exercitationem corrupti facilis suscipit. Impedit distinctio expedita tempora itaque. Omnis quisquam eaque iure alias officia. Consequatur molestiae error nostrum consectetur sint perferendis. Nesciunt fugit dolorem dolorum sed totam nulla occaecati. Qui quas aliquam occaecati harum consequatur ratione temporibus perspiciatis. Eos labore officia commodi quisquam. Odio expedita necessitatibus minus non rem pariatur dignissimos voluptatum. Illum molestiae totam perferendis repudiandae consectetur maxime. Tenetur architecto qui voluptatem culpa sint aspernatur eum voluptates. Suscipit reiciendis eveniet error quae temporibus enim. Atque quia repellat sequi dignissimos nostrum soluta perspiciatis aliquam. Iste quis similique eaque in. Sint voluptatum saepe pariatur aspernatur est nisi odio. Sequi atque porro nihil possimus dolorem eum. Laboriosam consectetur vitae iusto autem tempora doloremque non. Sint rerum esse cumque reprehenderit consequuntur ad non ratione. Earum quo quae reiciendis facere. description_html: |- Minima esse id porro impedit aliquid quam sint. Vero exercitationem voluptate consequatur fuga eos dolorum corrupti recusandae. Non similique facere beatae repudiandae exercitationem corrupti facilis suscipit. Impedit distinctio expedita tempora itaque. Omnis quisquam eaque iure alias officia. Consequatur molestiae error nostrum consectetur sint perferendis. Nesciunt fugit dolorem dolorum sed totam nulla occaecati. Qui quas aliquam occaecati harum consequatur ratione temporibus perspiciatis. Eos labore officia commodi quisquam. Odio expedita necessitatibus minus non rem pariatur dignissimos voluptatum. Illum molestiae totam perferendis repudiandae consectetur maxime. Tenetur architecto qui voluptatem culpa sint aspernatur eum voluptates. Suscipit reiciendis eveniet error quae temporibus enim. Atque quia repellat sequi dignissimos nostrum soluta perspiciatis aliquam. Iste quis similique eaque in. Sint voluptatum saepe pariatur aspernatur est nisi odio. Sequi atque porro nihil possimus dolorem eum. Laboriosam consectetur vitae iusto autem tempora doloremque non. Sint rerum esse cumque reprehenderit consequuntur ad non ratione. Earum quo quae reiciendis facere. default_variant_id: variant_UkLWZg9DAJ thumbnail_url: tags: [] price: id: price_UkLWZg9DAJ amount: '19.99' amount_in_cents: 1999 compare_at_amount: compare_at_amount_in_cents: currency: USD display_amount: "$19.99" display_compare_at_amount: price_list_id: variant_id: variant_UkLWZg9DAJ created_at: '2026-06-12T17:25:04.038Z' updated_at: '2026-06-12T17:25:04.038Z' original_price: status: active metadata: {} deleted_at: created_at: '2026-06-12T17:25:04.024Z' updated_at: '2026-06-12T17:25:04.344Z' tax_category_id: taxcat_UkLWZg9DAJ schema: "$ref": "#/components/schemas/Product" '422': description: validation error content: application/json: example: error: code: validation_error message: Name can't be blank details: name: - can't be blank schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: name: type: string example: Premium T-Shirt description: type: string slug: type: string status: type: string enum: - draft - active - archived tax_category_id: type: string description: Tax category ID category_ids: type: array items: type: string description: Array of category IDs tags: type: array items: type: string example: - eco - sale variants: type: array description: Array of variant payloads. Variants can declare multiple option pairs via `options:` and per-currency prices via `prices:`. Stock counts go in `stock_items:` (per stock location). items: type: object properties: sku: type: string options: type: array description: One pair per option type the variant participates in (e.g. size + color). Option types and values are auto-created if missing. items: type: object required: - name - value properties: name: type: string example: size value: type: string example: Small prices: type: array description: Per-currency prices. Upserted by currency. items: type: object required: - currency - amount properties: currency: type: string example: USD amount: type: number example: 29.99 compare_at_amount: type: number example: 39.99 stock_items: type: array description: Per-stock-location inventory. Upserted by stock_location_id. items: type: object required: - stock_location_id - count_on_hand properties: stock_location_id: type: string description: Stock location ID (e.g. sloc_xxx) count_on_hand: type: integer example: 50 backorderable: type: boolean delete: summary: Delete a product tags: - Products security: - api_key: [] bearer_auth: [] description: |- Soft-deletes a product. **Required scope:** `write_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.products.delete('prod_86Rf07xd4z') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: id in: path required: true description: Product ID schema: type: string responses: '204': description: product deleted "/api/v3/admin/products/bulk_status_update": post: summary: Bulk-update product status tags: - Products security: - api_key: [] bearer_auth: [] description: |- Sets `status` on each product in `ids`. Reindexes the affected products for search. Cross-store IDs are silently dropped. Returns counts. **Required scope:** `write_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: cross-store products silently dropped content: application/json: example: product_count: 0 status: archived schema: type: object properties: product_count: type: integer status: type: string '422': description: invalid status content: application/json: example: error: code: invalid_status message: Invalid status schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object required: - ids - status properties: ids: type: array items: type: string example: - prod_UkLWZg9DAJ status: type: string enum: - draft - active - archived example: archived "/api/v3/admin/products/bulk_add_to_categories": post: summary: Bulk-add products to categories tags: - Products security: - api_key: [] bearer_auth: [] description: |- Attaches each product in `ids` to every category (taxon) in `category_ids`. Categories from sibling stores are silently ignored. **Required scope:** `write_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: products added to categories content: application/json: example: product_count: 1 category_count: 1 schema: type: object properties: product_count: type: integer category_count: type: integer requestBody: content: application/json: schema: type: object required: - ids - category_ids properties: ids: type: array items: type: string category_ids: type: array items: type: string "/api/v3/admin/products/bulk_remove_from_categories": post: summary: Bulk-remove products from categories tags: - Products security: - api_key: [] bearer_auth: [] description: |- Detaches each product in `ids` from every category in `category_ids`. **Required scope:** `write_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: products removed from categories content: application/json: example: product_count: 1 category_count: 1 requestBody: content: application/json: schema: type: object required: - ids - category_ids properties: ids: type: array items: type: string category_ids: type: array items: type: string "/api/v3/admin/products/bulk_add_to_channels": post: summary: Bulk-add products to channels tags: - Products security: - api_key: [] bearer_auth: [] description: |- Publishes each product in `ids` on every channel in `channel_ids`. Idempotent — re-publishing on an existing channel is a no-op. Channels from sibling stores are silently ignored. **Required scope:** `write_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: products published on channels content: application/json: example: product_count: 1 channel_count: 1 schema: type: object properties: product_count: type: integer channel_count: type: integer requestBody: content: application/json: schema: type: object required: - ids - channel_ids properties: ids: type: array items: type: string channel_ids: type: array items: type: string "/api/v3/admin/products/bulk_remove_from_channels": post: summary: Bulk-remove products from channels tags: - Products security: - api_key: [] bearer_auth: [] description: |- Unpublishes each product in `ids` from every channel in `channel_ids`. **Required scope:** `write_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: products unpublished from channels content: application/json: example: product_count: 1 channel_count: 1 removed: 1 schema: type: object properties: product_count: type: integer channel_count: type: integer removed: type: integer requestBody: content: application/json: schema: type: object required: - ids - channel_ids properties: ids: type: array items: type: string channel_ids: type: array items: type: string "/api/v3/admin/products/bulk_add_tags": post: summary: Bulk-add tags to products tags: - Products security: - api_key: [] bearer_auth: [] description: |- Adds each tag name in `tags` to every product in `ids`. Tags are upserted by name. **Required scope:** `write_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: tags added content: application/json: example: product_count: 1 tag_count: 2 schema: type: object properties: product_count: type: integer tag_count: type: integer requestBody: content: application/json: schema: type: object required: - ids - tags properties: ids: type: array items: type: string tags: type: array items: type: string example: - summer - sale "/api/v3/admin/products/bulk_remove_tags": post: summary: Bulk-remove tags from products tags: - Products security: - api_key: [] bearer_auth: [] description: |- Removes each tag in `tags` from every product in `ids`. **Required scope:** `write_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: tags removed content: application/json: example: product_count: 1 tag_count: 1 requestBody: content: application/json: schema: type: object required: - ids - tags properties: ids: type: array items: type: string tags: type: array items: type: string "/api/v3/admin/products/bulk_destroy": delete: summary: Bulk-delete products tags: - Products security: - api_key: [] bearer_auth: [] description: |- Soft-deletes each product in `ids`. Returns the count actually destroyed. **Required scope:** `write_products` (for API-key authentication). parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: products deleted content: application/json: example: product_count: 1 schema: type: object properties: product_count: type: integer requestBody: content: application/json: schema: type: object required: - ids properties: ids: type: array items: type: string "/api/v3/admin/promotions/{promotion_id}/coupon_codes": parameters: - name: promotion_id in: path required: true schema: type: string get: summary: List coupon codes for a promotion tags: - Promotions security: - api_key: [] bearer_auth: [] description: |- Returns the auto-generated coupon codes for a multi-code promotion. Single-code promotions store the code on the promotion itself; this endpoint returns an empty list for them. **Required scope:** `read_promotions` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: coupons } = await client.promotions.couponCodes.list('promo_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: coupon codes found content: application/json: example: data: - id: coupon_UkLWZg9DAJ code: AAA111 state: unused created_at: '2026-06-12T17:23:52.481Z' updated_at: '2026-06-12T17:23:52.481Z' promotion_id: promo_UkLWZg9DAJ order_id: - id: coupon_gbHJdmfrXB code: BBB222 state: unused created_at: '2026-06-12T17:23:52.483Z' updated_at: '2026-06-12T17:23:52.483Z' promotion_id: promo_UkLWZg9DAJ order_id: meta: page: 1 limit: 25 count: 2 pages: 1 from: 1 to: 2 in: 2 previous: next: "/api/v3/admin/promotions/{promotion_id}/promotion_actions": parameters: - name: promotion_id in: path required: true schema: type: string get: summary: List actions for a promotion tags: - Promotions security: - api_key: [] bearer_auth: [] description: "**Required scope:** `read_promotions` (for API-key authentication)." x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: actions } = await client.promotions.actions.list('promo_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: actions found content: application/json: example: data: - id: pact_UkLWZg9DAJ created_at: '2026-06-12T17:25:08.639Z' updated_at: '2026-06-12T17:25:08.639Z' type: free_shipping promotion_id: promo_UkLWZg9DAJ preferences: {} preference_schema: [] label: Free shipping calculator: line_items: meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: post: summary: Create an action on a promotion tags: - Promotions security: - api_key: [] bearer_auth: [] description: |- Adds a new action to a promotion. The `type` is the wire shorthand from `GET /promotion_actions/types` (e.g. `free_shipping`, `create_item_adjustments`). Fully-qualified Ruby class names are also accepted for backward compatibility. **Required scope:** `write_promotions` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const action = await client.promotions.actions.create('promo_UkLWZg9DAJ', { type: 'free_shipping', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '201': description: action created content: application/json: example: id: pact_UkLWZg9DAJ created_at: '2026-06-12T17:25:09.232Z' updated_at: '2026-06-12T17:25:09.232Z' type: free_shipping promotion_id: promo_UkLWZg9DAJ preferences: {} preference_schema: [] label: Free shipping calculator: line_items: '422': description: unknown action type content: application/json: example: error: code: unknown_promotion_action_type message: Unknown type requestBody: content: application/json: schema: type: object properties: type: type: string example: free_shipping preferences: type: object additionalProperties: true required: - type "/api/v3/admin/promotions/{promotion_id}/promotion_actions/{id}": parameters: - name: promotion_id in: path required: true schema: type: string - name: id in: path required: true schema: type: string delete: summary: Delete an action from a promotion tags: - Promotions security: - api_key: [] bearer_auth: [] description: "**Required scope:** `write_promotions` (for API-key authentication)." parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '204': description: action deleted "/api/v3/admin/promotions/{promotion_id}/promotion_rules": parameters: - name: promotion_id in: path required: true schema: type: string get: summary: List rules for a promotion tags: - Promotions security: - api_key: [] bearer_auth: [] description: "**Required scope:** `read_promotions` (for API-key authentication)." x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: rules } = await client.promotions.rules.list('promo_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: rules found content: application/json: example: data: - id: prorule_UkLWZg9DAJ created_at: '2026-06-12T17:25:09.944Z' updated_at: '2026-06-12T17:25:09.944Z' type: currency promotion_id: promo_UkLWZg9DAJ preferences: currency: USD preference_schema: - key: currency type: string default: label: Currency product_ids: category_ids: customer_ids: meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: post: summary: Create a rule on a promotion tags: - Promotions security: - api_key: [] bearer_auth: [] description: |- Adds a new rule to a promotion. The `type` is the wire shorthand from `GET /promotion_rules/types` (e.g. `currency`, `item_total`, `product`). Fully-qualified Ruby class names are also accepted for backward compatibility. **Required scope:** `write_promotions` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const rule = await client.promotions.rules.create('promo_UkLWZg9DAJ', { type: 'currency', preferences: { currency: 'EUR' }, }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '201': description: rule created with preferences content: application/json: example: id: prorule_UkLWZg9DAJ created_at: '2026-06-12T17:25:10.546Z' updated_at: '2026-06-12T17:25:10.546Z' type: currency promotion_id: promo_UkLWZg9DAJ preferences: currency: EUR preference_schema: - key: currency type: string default: label: Currency product_ids: category_ids: customer_ids: '422': description: unknown rule type content: application/json: example: error: code: unknown_promotion_rule_type message: Unknown type requestBody: content: application/json: schema: type: object properties: type: type: string example: currency preferences: type: object additionalProperties: true required: - type "/api/v3/admin/promotions/{promotion_id}/promotion_rules/{id}": parameters: - name: promotion_id in: path required: true schema: type: string - name: id in: path required: true schema: type: string patch: summary: Update a rule's preferences tags: - Promotions security: - api_key: [] bearer_auth: [] description: "**Required scope:** `write_promotions` (for API-key authentication)." parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: rule updated content: application/json: example: id: prorule_UkLWZg9DAJ created_at: '2026-06-12T17:25:10.853Z' updated_at: '2026-06-12T17:25:11.135Z' type: currency promotion_id: promo_UkLWZg9DAJ preferences: currency: GBP preference_schema: - key: currency type: string default: label: Currency product_ids: category_ids: customer_ids: requestBody: content: application/json: schema: type: object properties: preferences: type: object additionalProperties: true delete: summary: Delete a rule from a promotion tags: - Promotions security: - api_key: [] bearer_auth: [] description: "**Required scope:** `write_promotions` (for API-key authentication)." parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '204': description: rule deleted "/api/v3/admin/promotions": get: summary: List promotions tags: - Promotions security: - api_key: [] bearer_auth: [] description: |- Returns the store's promotions, including manual coupon and automatic promotions. **Required scope:** `read_promotions` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: promotions } = await client.promotions.list() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: promotions found content: application/json: example: data: - id: promo_UkLWZg9DAJ name: Summer Sale description: code: summer starts_at: '2026-06-12T17:25:11.475Z' expires_at: usage_limit: match_policy: all path: kind: coupon_code multi_codes: false number_of_codes: code_prefix: promotion_category_id: metadata: {} created_at: '2026-06-12T17:25:11.477Z' updated_at: '2026-06-12T17:25:11.479Z' action_ids: [] rule_ids: [] meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: post: summary: Create a promotion tags: - Promotions security: - api_key: [] bearer_auth: [] description: |- Creates a new promotion. `code` is required for single-code coupon promotions; pass `multi_codes: true` with `number_of_codes` to auto-generate a batch. Rules and actions can be created in the same request by passing arrays of `{ type, preferences, ... }` rows. The server reconciles to the desired set: new rows are built, existing rows (by `id`) are updated, omitted rows are removed. **Required scope:** `write_promotions` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) // Single coupon code, no rules/actions const promotion = await client.promotions.create({ name: 'Black Friday', code: 'BLACKFRIDAY', starts_at: '2026-11-29T00:00:00Z', expires_at: '2026-12-01T00:00:00Z', }) // One-shot: promotion + rules + actions in a single request const blackFriday = await client.promotions.create({ name: 'Black Friday', code: 'BLACKFRIDAY', kind: 'coupon_code', starts_at: '2026-11-29T00:00:00Z', expires_at: '2026-12-01T00:00:00Z', match_policy: 'all', rules: [ { type: 'currency', preferences: { currency: 'USD' }, }, { type: 'item_total', preferences: { amount_min: 100, operator_min: 'gte' }, }, { type: 'product', preferences: { match_policy: 'any' }, product_ids: ['prod_abc123', 'prod_def456'], }, ], actions: [ { type: 'create_item_adjustments', calculator: { type: 'percent_on_line_item', preferences: { percent: 25 }, }, }, { type: 'free_shipping' }, ], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '201': description: promotion created with rules and actions content: application/json: example: id: promo_gbHJdmfrXB name: Black Friday description: code: blackfriday-os starts_at: '2026-06-12T17:25:12.469Z' expires_at: usage_limit: match_policy: all path: kind: coupon_code multi_codes: false number_of_codes: code_prefix: promotion_category_id: metadata: {} created_at: '2026-06-12T17:25:12.471Z' updated_at: '2026-06-12T17:25:12.495Z' action_ids: - pact_UkLWZg9DAJ - pact_gbHJdmfrXB rule_ids: - prorule_UkLWZg9DAJ - prorule_gbHJdmfrXB - prorule_EfhxLZ9ck8 '422': description: invalid params content: application/json: example: error: code: validation_error message: Name can't be blank and Code can't be blank details: name: - can't be blank code: - can't be blank requestBody: content: application/json: schema: type: object properties: name: type: string code: type: string nullable: true description: type: string nullable: true starts_at: type: string format: date-time nullable: true expires_at: type: string format: date-time nullable: true usage_limit: type: integer nullable: true match_policy: type: string enum: - all - any kind: type: string enum: - coupon_code - automatic multi_codes: type: boolean number_of_codes: type: integer nullable: true code_prefix: type: string nullable: true promotion_category_id: type: string nullable: true rules: type: array items: type: object properties: type: type: string example: currency preferences: type: object additionalProperties: true product_ids: type: array items: type: string category_ids: type: array items: type: string customer_ids: type: array items: type: string required: - type actions: type: array items: type: object properties: type: type: string example: free_shipping preferences: type: object additionalProperties: true calculator: type: object properties: type: type: string example: flat_percent_item_total preferences: type: object additionalProperties: true required: - type required: - name "/api/v3/admin/promotions/{id}": get: summary: Show a promotion tags: - Promotions security: - api_key: [] bearer_auth: [] description: "**Required scope:** `read_promotions` (for API-key authentication)." parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '200': description: promotion found content: application/json: example: id: promo_UkLWZg9DAJ name: Summer Sale description: code: summer starts_at: '2026-06-12T17:25:12.804Z' expires_at: usage_limit: match_policy: all path: kind: coupon_code multi_codes: false number_of_codes: code_prefix: promotion_category_id: metadata: {} created_at: '2026-06-12T17:25:12.805Z' updated_at: '2026-06-12T17:25:12.806Z' action_ids: [] rule_ids: [] patch: summary: Update a promotion tags: - Promotions security: - api_key: [] bearer_auth: [] description: |- Updates a promotion. The `rules` and `actions` arrays are treated as a *desired set* — rows with `id` update in place, rows without `id` are built fresh, and any existing row not present in the array is destroyed. Pass `rules: []` or `actions: []` to clear them. **Required scope:** `write_promotions` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) // Basic field update await client.promotions.update(promotionId, { description: 'Updated description', }) // One-shot: rewrite rules + actions in a single request await client.promotions.update(promotionId, { name: 'Holiday Sale', rules: [ // Update an existing rule by id — `preferences` overwrite the prior set { id: 'prorule_existing', type: 'currency', preferences: { currency: 'EUR' }, }, // Add a new rule { type: 'item_total', preferences: { amount_min: 50, operator_min: 'gte' }, }, ], actions: [ // Swap calculator type on an existing action { id: 'proaction_existing', type: 'create_item_adjustments', calculator: { type: 'percent_on_line_item', preferences: { percent: 15 }, }, }, ], }) // Remove all rules/actions await client.promotions.update(promotionId, { rules: [], actions: [], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '200': description: rules and actions cleared with empty arrays content: application/json: example: id: promo_UkLWZg9DAJ name: Summer Sale description: code: summer starts_at: '2026-06-12T17:25:13.717Z' expires_at: usage_limit: match_policy: all path: kind: coupon_code multi_codes: false number_of_codes: code_prefix: promotion_category_id: metadata: {} created_at: '2026-06-12T17:25:13.718Z' updated_at: '2026-06-12T17:25:14.003Z' action_ids: [] rule_ids: [] requestBody: content: application/json: schema: type: object properties: name: type: string description: type: string nullable: true code: type: string nullable: true starts_at: type: string format: date-time nullable: true expires_at: type: string format: date-time nullable: true usage_limit: type: integer nullable: true match_policy: type: string enum: - all - any kind: type: string enum: - coupon_code - automatic promotion_category_id: type: string nullable: true rules: type: array items: type: object properties: id: type: string nullable: true description: Pass to update an existing rule; omit to build a new one type: type: string example: currency preferences: type: object additionalProperties: true product_ids: type: array items: type: string category_ids: type: array items: type: string customer_ids: type: array items: type: string required: - type actions: type: array items: type: object properties: id: type: string nullable: true type: type: string example: free_shipping preferences: type: object additionalProperties: true calculator: type: object properties: type: type: string example: flat_percent_item_total preferences: type: object additionalProperties: true required: - type delete: summary: Delete a promotion tags: - Promotions security: - api_key: [] bearer_auth: [] description: "**Required scope:** `write_promotions` (for API-key authentication)." parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '204': description: promotion deleted "/api/v3/admin/promotion_actions/types": get: summary: List available promotion action types tags: - Promotions security: - api_key: [] bearer_auth: [] description: |- Returns the registered Spree::PromotionAction subclasses with their preference schemas. Used by admin UIs to populate the "Add action" picker and render generic preference forms. **Required scope:** `read_promotions` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: actionTypes } = await client.promotionActions.types() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: action types found content: application/json: example: data: - type: create_line_items label: Create line items description: preference_schema: [] - type: create_item_adjustments label: Create per-line-item adjustment description: preference_schema: [] - type: create_adjustment label: Create whole-order adjustment description: preference_schema: [] - type: free_shipping label: Free shipping description: preference_schema: [] "/api/v3/admin/promotion_rules/types": get: summary: List available promotion rule types tags: - Promotions security: - api_key: [] bearer_auth: [] description: |- Returns the registered Spree::PromotionRule subclasses with their preference schemas. **Required scope:** `read_promotions` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: ruleTypes } = await client.promotionRules.types() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: rule types found content: application/json: example: data: - type: category label: Categories description: preference_schema: - key: match_policy type: string default: any - type: country label: Country description: preference_schema: - key: country_isos type: array default: [] - key: country_id type: integer default: - key: country_iso type: string default: - type: currency label: Currency description: preference_schema: - key: currency type: string default: - type: customer_group label: Customer Group(s) description: preference_schema: - key: customer_group_ids type: array default: [] - type: customer label: Customers description: preference_schema: [] - type: first_order label: First order description: preference_schema: [] - type: item_total label: Item total description: preference_schema: - key: amount_min type: decimal default: 100.0 - key: operator_min type: string default: ">" - key: amount_max type: decimal default: - key: operator_max type: string default: "<" - type: one_use_per_user label: One Use Per User description: preference_schema: [] - type: customer_logged_in label: Only logged in customers description: preference_schema: [] - type: option_value label: Option Value(s) description: preference_schema: - key: eligible_values type: array default: [] - key: match_policy type: string default: any - type: product label: Product(s) description: preference_schema: - key: match_policy type: string default: any "/api/v3/admin/orders/{order_id}/refunds": get: summary: List refunds tags: - Refunds security: - api_key: [] bearer_auth: [] description: |- Returns all refunds for an order. **Required scope:** `read_refunds` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: refunds } = await client.orders.refunds.list('or_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., payment, refund_reason). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., amount,reason,transaction_id). id is always included. schema: type: string responses: '200': description: refunds found content: application/json: example: data: [] meta: page: 1 limit: 25 count: 0 pages: 1 from: 0 to: 0 in: 0 previous: next: post: summary: Create a refund tags: - Refunds security: - api_key: [] bearer_auth: [] description: |- Creates a refund for a payment on the order. The refund is automatically processed via the payment gateway. **Required scope:** `write_refunds` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const refund = await client.orders.refunds.create('or_UkLWZg9DAJ', { payment_id: 'pay_UkLWZg9DAJ', amount: 5.00, refund_reason_id: 'refrsn_UkLWZg9DAJ', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: order_id in: path required: true description: Order ID schema: type: string responses: '201': description: refund created content: application/json: example: id: re_UkLWZg9DAJ transaction_id: BGS-68aa088bc90d amount: '5.0' payment_id: py_UkLWZg9DAJ refund_reason_id: rr_UkLWZg9DAJ reimbursement_id: metadata: {} created_at: '2026-06-12T17:24:40.748Z' updated_at: '2026-06-12T17:24:40.748Z' requestBody: content: application/json: schema: type: object required: - payment_id - amount properties: payment_id: type: string description: Payment ID amount: type: number example: 10.0 refund_reason_id: type: string description: Refund reason ID "/api/v3/admin/store_credit_categories": get: summary: List store credit categories tags: - Settings security: - api_key: [] bearer_auth: [] description: |- Returns the configured store credit categories. Categories classify store credits (e.g., "Goodwill", "Gift Card", "Refund") and surface in the admin UI as a dropdown when issuing or editing a store credit. Category names matching `Spree::Config[:non_expiring_credit_types]` are flagged via `non_expiring: true`. **Required scope:** `read_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: categories } = await client.storeCreditCategories.list() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: page in: query required: false description: Page number schema: type: integer - name: limit in: query required: false description: Number of records per page schema: type: integer - name: q[name_cont] in: query required: false description: Filter by name (contains) schema: type: string - name: sort in: query required: false description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include. id is always included. schema: type: string responses: '200': description: store credit categories found content: application/json: example: data: - id: sccat_UkLWZg9DAJ name: Goodwill created_at: '2026-06-12T17:25:17.833Z' updated_at: '2026-06-12T17:25:17.833Z' non_expiring: false meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: schema: type: object properties: data: type: array items: "$ref": "#/components/schemas/StoreCreditCategory" meta: "$ref": "#/components/schemas/PaginationMeta" required: - data - meta '401': description: unauthorized content: application/json: example: error: code: authentication_required message: Authentication required schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v3/admin/store_credit_categories/{id}": parameters: - name: id in: path required: true description: Store credit category ID schema: type: string get: summary: Get a store credit category tags: - Settings security: - api_key: [] bearer_auth: [] description: |- Returns a single store credit category by prefixed ID. **Required scope:** `read_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const category = await client.storeCreditCategories.get('sccat_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include. id is always included. schema: type: string responses: '200': description: store credit category found content: application/json: example: id: sccat_UkLWZg9DAJ name: Goodwill created_at: '2026-06-12T17:25:18.145Z' updated_at: '2026-06-12T17:25:18.145Z' non_expiring: false schema: "$ref": "#/components/schemas/StoreCreditCategory" '404': description: store credit category not found content: application/json: example: error: code: record_not_found message: Store credit category not found schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v3/admin/store": get: summary: Get the current store tags: - Settings security: - api_key: [] bearer_auth: [] description: |- Returns the current store configuration. The store is resolved from the request context (host or admin selection); there is no `id` parameter. **Required scope:** `read_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const store = await client.store.get() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '200': description: current store content: application/json: example: id: store_UkLWZg9DAJ metadata: {} name: Spree Test Store default_currency: USD default_locale: en mail_from_address: no-reply@example.com customer_support_email: support@example.com new_order_notifications_email: store-owner@example.com preferred_send_consumer_transactional_emails: true preferred_admin_locale: preferred_timezone: UTC preferred_weight_unit: lb preferred_unit_system: imperial created_at: '2026-06-12T17:23:41.091Z' updated_at: '2026-06-12T17:25:18.763Z' url: http://www.example.com:3000 supported_currencies: - USD supported_locales: - en logo_url: mailer_logo_url: schema: "$ref": "#/components/schemas/Store" '401': description: unauthorized content: application/json: example: error: code: authentication_required message: Authentication required schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update the current store tags: - Settings security: - api_key: [] bearer_auth: [] description: |- Updates the current store configuration. **Required scope:** `write_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const store = await client.store.update({ name: 'My Store' }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '200': description: store updated content: application/json: example: id: store_UkLWZg9DAJ metadata: {} name: Renamed Store default_currency: USD default_locale: en mail_from_address: no-reply@example.com customer_support_email: support@example.com new_order_notifications_email: store-owner@example.com preferred_send_consumer_transactional_emails: true preferred_admin_locale: preferred_timezone: UTC preferred_weight_unit: lb preferred_unit_system: imperial created_at: '2026-06-12T17:23:41.091Z' updated_at: '2026-06-12T17:25:19.408Z' url: http://www.example.com:3000 supported_currencies: - USD supported_locales: - en logo_url: mailer_logo_url: schema: "$ref": "#/components/schemas/Store" '422': description: validation error content: application/json: example: error: code: validation_error message: Site Name can't be blank details: name: - can't be blank schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: name: type: string example: My Store preferred_admin_locale: type: string example: en preferred_timezone: type: string example: UTC preferred_weight_unit: type: string example: kg preferred_unit_system: type: string example: metric "/api/v3/admin/tags": get: summary: List tags tags: - Settings security: - api_key: [] bearer_auth: [] description: Returns tag names for a given taggable type. Used for autocomplete in tag inputs on products, orders, and customers. x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: tags } = await client.tags.list({ taggable_type: 'Spree::User', q: 'vip', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: taggable_type in: query required: true description: Taggable type (`Spree::Product`, `Spree::Order`, or `Spree::User`) schema: type: string - name: q in: query required: false description: Optional case-insensitive substring filter schema: type: string responses: '200': description: tags found content: application/json: example: data: - name: vip - name: wholesale '422': description: invalid taggable type content: application/json: example: error: code: invalid_taggable_type message: taggable_type must be one of Spree::Product, Spree::Order, Spree::LegacyUser "/api/v3/admin/admin_users": get: summary: List staff tags: - Staff security: - api_key: [] bearer_auth: [] description: |- Returns admin users with at least one role assignment on the current store. **Required scope:** `read_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: staff } = await client.adminUsers.list() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: staff found content: application/json: example: data: - id: admin_UkLWZg9DAJ email: latricia.mertz@wiegand.name first_name: Jetta last_name: Rodriguez full_name: Jetta Rodriguez created_at: '2026-06-12T17:23:41.426Z' updated_at: '2026-06-12T17:23:41.426Z' roles: - id: role_UkLWZg9DAJ name: admin meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: "/api/v3/admin/admin_users/{id}": get: summary: Show a staff member tags: - Staff security: - api_key: [] bearer_auth: [] description: "**Required scope:** `read_settings` (for API-key authentication)." x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const staff = await client.adminUsers.get('admin_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '200': description: staff member found content: application/json: example: id: admin_UkLWZg9DAJ email: keiko@bechtelargrady.ca first_name: Rosemary last_name: Lang full_name: Rosemary Lang created_at: '2026-06-12T17:23:41.772Z' updated_at: '2026-06-12T17:23:41.772Z' roles: - id: role_UkLWZg9DAJ name: admin patch: summary: Update a staff member tags: - Staff security: - api_key: [] bearer_auth: [] description: |- Updates name fields and reassigns roles for the current store. `role_ids` is a complete replacement — roles not in the array are removed for this store. **Required scope:** `write_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const staff = await client.adminUsers.update('admin_xxx', { first_name: 'Ada', role_ids: ['role_xxx'] }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '200': description: staff member updated content: application/json: example: id: admin_UkLWZg9DAJ email: leona.kuhn@ullrichemard.info first_name: Renamed last_name: Jacobson full_name: Renamed Jacobson created_at: '2026-06-12T17:23:42.066Z' updated_at: '2026-06-12T17:23:42.082Z' roles: - id: role_UkLWZg9DAJ name: admin requestBody: content: application/json: schema: type: object properties: first_name: type: string example: Ada last_name: type: string example: Lovelace role_ids: type: array items: type: string delete: summary: Remove a staff member from this store tags: - Staff security: - api_key: [] bearer_auth: [] description: |- Removes the user's role assignments on the current store. The account is preserved — the user keeps access to any other stores. **Required scope:** `write_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.adminUsers.delete('admin_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '204': description: staff removed from store "/api/v3/admin/invitations": get: summary: List invitations tags: - Staff security: - api_key: [] bearer_auth: [] description: |- Returns invitations for the current store, including pending and accepted. **Required scope:** `read_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: invitations } = await client.invitations.list() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: invitations found content: application/json: example: data: - id: inv_UkLWZg9DAJ email: tracee_maggio@schroeder.us status: pending created_at: '2026-06-12T17:24:18.489Z' updated_at: '2026-06-12T17:24:18.489Z' expires_at: '2026-06-26T17:24:18.486Z' role_id: role_UkLWZg9DAJ role_name: admin inviter_email: caitlin_terry@kshlerinboehm.ca acceptance_url: "/accept-invitation/inv_UkLWZg9DAJ?token=kvK81PwqFhrhTCgxQsWkHEC5" invitee_exists: false store: id: store_UkLWZg9DAJ name: Spree Test Store meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: post: summary: Create an invitation tags: - Staff security: - api_key: [] bearer_auth: [] description: |- Invites a teammate by email. The invitation is scoped to the current store and carries the chosen role; on accept, a `RoleUser` is created via the invitation's `after_accept` callback. **Required scope:** `write_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const invitation = await client.invitations.create({ email: 'ada@example.com', role_id: 'role_xxx' }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '201': description: invitation created content: application/json: example: id: inv_gbHJdmfrXB email: new-staff@example.com status: pending created_at: '2026-06-12T17:24:18.802Z' updated_at: '2026-06-12T17:24:18.802Z' expires_at: '2026-06-26T17:24:18.799Z' role_id: role_UkLWZg9DAJ role_name: admin inviter_email: michel@upton.biz acceptance_url: "/accept-invitation/inv_gbHJdmfrXB?token=jkitRfxSPJyDt1bngSSRBWic" invitee_exists: false store: id: store_UkLWZg9DAJ name: Spree Test Store requestBody: content: application/json: schema: type: object required: - email - role_id properties: email: type: string example: ada@example.com role_id: type: string example: role_xxx "/api/v3/admin/invitations/{id}": delete: summary: Revoke an invitation tags: - Staff security: - api_key: [] bearer_auth: [] description: "**Required scope:** `write_settings` (for API-key authentication)." x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.invitations.delete('inv_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '204': description: invitation revoked "/api/v3/admin/invitations/{id}/resend": patch: summary: Resend an invitation tags: - Staff security: - api_key: [] bearer_auth: [] description: |- Issues a fresh token and dispatches the invitation email again. **Required scope:** `write_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const invitation = await client.invitations.resend('inv_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string - name: id in: path required: true schema: type: string responses: '200': description: invitation resent content: application/json: example: id: inv_UkLWZg9DAJ email: lacie@ratke.co.uk status: pending created_at: '2026-06-12T17:24:19.385Z' updated_at: '2026-06-12T17:24:19.385Z' expires_at: '2026-06-26T17:24:19.383Z' role_id: role_UkLWZg9DAJ role_name: admin inviter_email: eldon.bailey@larkin.biz acceptance_url: "/accept-invitation/inv_UkLWZg9DAJ?token=XnbTqpmFxFnkvNBc81ve5JRL" invitee_exists: false store: id: store_UkLWZg9DAJ name: Spree Test Store "/api/v3/admin/roles": get: summary: List roles tags: - Staff security: - api_key: [] bearer_auth: [] description: |- Returns the roles available for staff role pickers. Roles are global, not per-store. **Required scope:** `read_settings` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: roles } = await client.roles.list() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true schema: type: string responses: '200': description: roles found content: application/json: example: data: - id: role_UkLWZg9DAJ name: admin created_at: '2026-06-12T17:25:14.947Z' updated_at: '2026-06-12T17:25:14.947Z' meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: "/api/v3/admin/stock_locations": get: summary: List stock locations tags: - Stock Locations security: - api_key: [] bearer_auth: [] description: |- Returns the configured stock locations. Stock locations are global (shared across stores). Filter with Ransack predicates such as `q[active_eq]`, `q[kind_eq]`, `q[pickup_enabled_eq]`, or `q[name_cont]`. Pickup-related attributes (`kind`, `pickup_enabled`, `pickup_stock_policy`, `pickup_ready_in_minutes`, `pickup_instructions`) drive merchant pickup support at checkout — customers can collect orders from any active location with `pickup_enabled: true`. **Required scope:** `read_stock` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: stockLocations } = await client.stockLocations.list() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: page in: query required: false description: Page number schema: type: integer - name: limit in: query required: false description: Number of records per page schema: type: integer - name: q[name_cont] in: query required: false description: Filter by name (contains) schema: type: string - name: q[active_eq] in: query required: false description: Filter by active status schema: type: boolean - name: q[kind_eq] in: query required: false description: 'Filter by kind (built-in: ''warehouse'', ''store'', ''fulfillment_center'')' schema: type: string - name: q[pickup_enabled_eq] in: query required: false description: Filter by pickup-enabled flag schema: type: boolean - name: sort in: query required: false description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include. id is always included. schema: type: string responses: '200': description: stock locations found content: application/json: example: data: - id: sloc_UkLWZg9DAJ state_abbr: STATE_ABBR_47 name: Brooklyn warehouse address1: 1600 Pennsylvania Ave NW city: Washington zipcode: '20500' country_iso: US country_name: United States of America state_text: STATE_ABBR_47 admin_name: address2: state_name: phone: "(202) 456-1111" company: active: true default: false backorderable_default: true propagate_all_variants: false kind: warehouse pickup_enabled: false pickup_stock_policy: local pickup_ready_in_minutes: pickup_instructions: created_at: '2026-06-12T17:25:15.247Z' updated_at: '2026-06-12T17:25:15.247Z' meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: schema: type: object properties: data: type: array items: "$ref": "#/components/schemas/StockLocation" meta: "$ref": "#/components/schemas/PaginationMeta" required: - data - meta '401': description: unauthorized content: application/json: example: error: code: authentication_required message: Authentication required schema: "$ref": "#/components/schemas/ErrorResponse" post: summary: Create a stock location tags: - Stock Locations security: - api_key: [] bearer_auth: [] description: |- Creates a new stock location. Setting `default: true` automatically demotes the previous default location. **Required scope:** `write_stock` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const stockLocation = await client.stockLocations.create({ name: 'Brooklyn warehouse', kind: 'warehouse', country_iso: 'US', state_abbr: 'NY', city: 'Brooklyn', zipcode: '11201', pickup_enabled: true, pickup_stock_policy: 'local', pickup_ready_in_minutes: 60, }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '201': description: stock location created content: application/json: example: id: sloc_gbHJdmfrXB state_abbr: name: Manhattan store address1: city: zipcode: country_iso: country_name: state_text: admin_name: address2: state_name: phone: company: active: true default: false backorderable_default: false propagate_all_variants: false kind: store pickup_enabled: true pickup_stock_policy: local pickup_ready_in_minutes: 30 pickup_instructions: created_at: '2026-06-12T17:25:15.845Z' updated_at: '2026-06-12T17:25:15.845Z' schema: "$ref": "#/components/schemas/StockLocation" '422': description: validation error content: application/json: example: error: code: validation_error message: Name can't be blank details: name: - can't be blank schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: name: type: string example: Brooklyn warehouse admin_name: type: string nullable: true description: Internal name shown only in the admin active: type: boolean example: true default: type: boolean description: Setting to true demotes the previous default. kind: type: string enum: - warehouse - store - fulfillment_center description: Categorizes the location. example: warehouse propagate_all_variants: type: boolean backorderable_default: type: boolean address1: type: string nullable: true address2: type: string nullable: true city: type: string nullable: true zipcode: type: string nullable: true phone: type: string nullable: true company: type: string nullable: true country_iso: type: string nullable: true description: ISO-3166 alpha-2 country code (e.g. "US"). state_abbr: type: string nullable: true description: State / province abbreviation (e.g. "NY"). Resolved against the selected country. state_name: type: string nullable: true description: Free-text state for countries without a states list. pickup_enabled: type: boolean pickup_stock_policy: type: string enum: - local - any description: "'local' = items at this location only; 'any' = transfer-eligible (ship-to-store)." pickup_ready_in_minutes: type: number nullable: true minimum: 0 pickup_instructions: type: string nullable: true required: - name "/api/v3/admin/stock_locations/{id}": parameters: - name: id in: path required: true description: Stock location ID schema: type: string get: summary: Get a stock location tags: - Stock Locations security: - api_key: [] bearer_auth: [] description: |- Returns a single stock location by prefixed ID. **Required scope:** `read_stock` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const stockLocation = await client.stockLocations.get('sloc_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include. id is always included. schema: type: string responses: '200': description: stock location found content: application/json: example: id: sloc_UkLWZg9DAJ state_abbr: STATE_ABBR_51 name: Brooklyn warehouse address1: 1600 Pennsylvania Ave NW city: Washington zipcode: '20500' country_iso: US country_name: United States of America state_text: STATE_ABBR_51 admin_name: address2: state_name: phone: "(202) 456-1111" company: active: true default: false backorderable_default: true propagate_all_variants: false kind: warehouse pickup_enabled: false pickup_stock_policy: local pickup_ready_in_minutes: pickup_instructions: created_at: '2026-06-12T17:25:16.140Z' updated_at: '2026-06-12T17:25:16.140Z' schema: "$ref": "#/components/schemas/StockLocation" '404': description: stock location not found content: application/json: example: error: code: record_not_found message: Stock location not found schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update a stock location tags: - Stock Locations security: - api_key: [] bearer_auth: [] description: |- Updates an existing stock location. Same address-field conventions as the create endpoint. Setting `default: true` automatically demotes the previous default. **Required scope:** `write_stock` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const stockLocation = await client.stockLocations.update('sloc_UkLWZg9DAJ', { pickup_enabled: true, pickup_ready_in_minutes: 45, pickup_instructions: 'Enter through the back door, ring the bell.', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '200': description: stock location updated content: application/json: example: id: sloc_UkLWZg9DAJ state_abbr: STATE_ABBR_53 name: Renamed warehouse address1: 1600 Pennsylvania Ave NW city: Washington zipcode: '20500' country_iso: US country_name: United States of America state_text: STATE_ABBR_53 admin_name: address2: state_name: phone: "(202) 456-1111" company: active: true default: false backorderable_default: true propagate_all_variants: false kind: warehouse pickup_enabled: true pickup_stock_policy: local pickup_ready_in_minutes: 45 pickup_instructions: created_at: '2026-06-12T17:25:16.866Z' updated_at: '2026-06-12T17:25:17.191Z' schema: "$ref": "#/components/schemas/StockLocation" '422': description: validation error content: application/json: example: error: code: validation_error message: Pickup stock policy is not included in the list details: pickup_stock_policy: - is not included in the list schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: name: type: string admin_name: type: string nullable: true active: type: boolean default: type: boolean kind: type: string enum: - warehouse - store - fulfillment_center propagate_all_variants: type: boolean backorderable_default: type: boolean address1: type: string nullable: true address2: type: string nullable: true city: type: string nullable: true zipcode: type: string nullable: true phone: type: string nullable: true company: type: string nullable: true country_iso: type: string nullable: true state_abbr: type: string nullable: true state_name: type: string nullable: true pickup_enabled: type: boolean pickup_stock_policy: type: string enum: - local - any pickup_ready_in_minutes: type: number nullable: true minimum: 0 pickup_instructions: type: string nullable: true delete: summary: Delete a stock location tags: - Stock Locations security: - api_key: [] bearer_auth: [] description: |- Soft-deletes the stock location (sets `deleted_at`). Existing fulfillments that referenced it keep the historical record via `Spree::StockLocation.with_deleted`. **Required scope:** `write_stock` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.stockLocations.delete('sloc_UkLWZg9DAJ') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '204': description: stock location deleted "/api/v3/admin/products/{product_id}/variants": get: summary: List product variants tags: - Variants security: - api_key: [] bearer_auth: [] description: |- Returns a paginated list of variants for a product, including the master variant. **Required scope:** `read_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const { data: variants } = await client.products.variants.list('prod_86Rf07xd4z', { expand: ['prices', 'stock_items'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: product_id in: path required: true description: Product ID schema: type: string - name: page in: query required: false description: Page number schema: type: integer - name: limit in: query required: false description: Number of records per page schema: type: integer - name: expand in: query required: false description: Comma-separated associations to expand (e.g., images, prices, stock_items, option_values). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., sku,price,stock). id is always included. schema: type: string responses: '200': description: variants found content: application/json: example: data: - id: variant_UkLWZg9DAJ product_id: prod_UkLWZg9DAJ sku: SKU-97 options_text: '' track_inventory: true media_count: 0 thumbnail_url: purchasable: false in_stock: false backorderable: false weight: 0.0 height: width: depth: price: id: amount: amount_in_cents: 0 compare_at_amount: compare_at_amount_in_cents: currency: USD display_amount: "$0.00" display_compare_at_amount: price_list_id: original_price: option_values: [] metadata: {} position: 1 cost_price: '17.0' cost_currency: USD barcode: weight_unit: lb dimensions_unit: deleted_at: created_at: '2026-06-12T17:25:20.879Z' updated_at: '2026-06-12T17:25:20.888Z' tax_category_id: taxcat_UkLWZg9DAJ available_stock: 0 reserved_quantity: 0 total_on_hand: 0 product_name: Product 79237 - id: variant_gbHJdmfrXB product_id: prod_UkLWZg9DAJ sku: SKU-98 options_text: 'Size: S' track_inventory: true media_count: 0 thumbnail_url: purchasable: true in_stock: false backorderable: true weight: 175.85 height: 52.53 width: 61.32 depth: 150.97 price: id: price_gbHJdmfrXB amount: '19.99' amount_in_cents: 1999 compare_at_amount: compare_at_amount_in_cents: currency: USD display_amount: "$19.99" display_compare_at_amount: price_list_id: original_price: option_values: - id: optval_UkLWZg9DAJ option_type_id: opt_UkLWZg9DAJ name: size-19 label: S position: 1 color_code: option_type_name: foo-size-28 option_type_label: Size image_url: metadata: {} created_at: '2026-06-12T17:25:20.901Z' updated_at: '2026-06-12T17:25:20.901Z' metadata: {} position: 2 cost_price: '17.0' cost_currency: USD barcode: weight_unit: lb dimensions_unit: deleted_at: created_at: '2026-06-12T17:25:20.899Z' updated_at: '2026-06-12T17:25:20.911Z' tax_category_id: taxcat_UkLWZg9DAJ available_stock: 0 reserved_quantity: 0 total_on_hand: 0 product_name: Product 79237 meta: page: 1 limit: 25 count: 2 pages: 1 from: 1 to: 2 in: 2 previous: next: post: summary: Create a variant tags: - Variants security: - api_key: [] bearer_auth: [] description: |- Creates a new variant for a product. Supports nested prices and stock items. Option types and values are auto-created if they don't exist. Prices are upserted by currency. Stock items are upserted by stock location. **Required scope:** `write_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const variant = await client.products.variants.create('prod_86Rf07xd4z', { sku: 'TSHIRT-L-NAVY', options: [ { name: 'size', value: 'Large' }, { name: 'color', value: 'navy' }, ], prices: [ { currency: 'USD', amount: 29.99, compare_at_amount: 34.99 }, { currency: 'EUR', amount: 27.99 }, ], stock_items: [ { stock_location_id: 'sloc_UkLWZg9DAJ', count_on_hand: 25 }, ], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: product_id in: path required: true description: Product ID schema: type: string responses: '201': description: variant created content: application/json: example: id: variant_EfhxLZ9ck8 product_id: prod_UkLWZg9DAJ sku: NEW-SKU-001 options_text: 'Size: XL' track_inventory: true media_count: 0 thumbnail_url: purchasable: false in_stock: false backorderable: false weight: 0.0 height: width: depth: price: id: price_EfhxLZ9ck8 amount: '24.99' amount_in_cents: 2499 compare_at_amount: compare_at_amount_in_cents: currency: USD display_amount: "$24.99" display_compare_at_amount: price_list_id: original_price: option_values: - id: optval_gbHJdmfrXB option_type_id: opt_gbHJdmfrXB name: xl label: XL position: 1 color_code: option_type_name: size option_type_label: Size image_url: metadata: {} created_at: '2026-06-12T17:25:21.569Z' updated_at: '2026-06-12T17:25:21.569Z' metadata: {} position: 3 cost_price: cost_currency: USD barcode: weight_unit: lb dimensions_unit: deleted_at: created_at: '2026-06-12T17:25:21.573Z' updated_at: '2026-06-12T17:25:21.575Z' tax_category_id: taxcat_UkLWZg9DAJ available_stock: 0 reserved_quantity: 0 total_on_hand: 0 product_name: Product 804516 '422': description: validation error content: application/json: example: error: code: validation_error message: Option value variants can't be blank details: option_value_variants: - can't be blank schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: sku: type: string example: SKU-001 price: type: number example: 29.99 compare_at_price: type: number example: 39.99 cost_price: type: number example: 10.0 cost_currency: type: string example: USD weight: type: number height: type: number width: type: number depth: type: number weight_unit: type: string dimensions_unit: type: string track_inventory: type: boolean tax_category_id: type: string options: type: array description: One pair per option type the variant participates in (e.g. size + color). Option types and values are auto-created if missing. items: type: object required: - name - value properties: name: type: string example: size value: type: string example: Small position: type: integer barcode: type: string prices: type: array description: Per-currency prices. Upserted by currency. items: type: object required: - currency - amount properties: currency: type: string example: USD amount: type: number example: 29.99 compare_at_amount: type: number example: 39.99 stock_items: type: array description: Per-stock-location inventory. Upserted by stock_location_id. items: type: object required: - stock_location_id - count_on_hand properties: stock_location_id: type: string description: Stock location ID (e.g. sloc_xxx) count_on_hand: type: integer example: 50 backorderable: type: boolean "/api/v3/admin/products/{product_id}/variants/{id}": get: summary: Get a variant tags: - Variants security: - api_key: [] bearer_auth: [] description: |- Returns a single variant by ID. **Required scope:** `read_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const variant = await client.products.variants.get('prod_86Rf07xd4z', 'variant_k5nR8xLq', { expand: ['prices', 'stock_items'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: product_id in: path required: true description: Product ID schema: type: string - name: id in: path required: true description: Variant ID schema: type: string - name: expand in: query required: false description: Comma-separated associations to expand (e.g., images, prices, stock_items, option_values). Use dot notation for nested expand (max 4 levels). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include (e.g., sku,price,stock). id is always included. schema: type: string responses: '200': description: variant found content: application/json: example: id: variant_gbHJdmfrXB product_id: prod_UkLWZg9DAJ sku: SKU-104 options_text: 'Size: S' track_inventory: true media_count: 0 thumbnail_url: purchasable: true in_stock: false backorderable: true weight: 1.16 height: 177.59 width: 10.65 depth: 151.88 price: id: price_gbHJdmfrXB amount: '19.99' amount_in_cents: 1999 compare_at_amount: compare_at_amount_in_cents: currency: USD display_amount: "$19.99" display_compare_at_amount: price_list_id: original_price: option_values: - id: optval_UkLWZg9DAJ option_type_id: opt_UkLWZg9DAJ name: size-22 label: S position: 1 color_code: option_type_name: foo-size-31 option_type_label: Size image_url: metadata: {} created_at: '2026-06-12T17:25:21.996Z' updated_at: '2026-06-12T17:25:21.996Z' metadata: {} position: 2 cost_price: '17.0' cost_currency: USD barcode: weight_unit: lb dimensions_unit: deleted_at: created_at: '2026-06-12T17:25:21.994Z' updated_at: '2026-06-12T17:25:22.006Z' tax_category_id: taxcat_UkLWZg9DAJ available_stock: 0 reserved_quantity: 0 total_on_hand: 0 product_name: Product 828789 '404': description: variant not found content: application/json: example: error: code: variant_not_found message: Variant not found schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update a variant tags: - Variants security: - api_key: [] bearer_auth: [] description: |- Updates a variant. Only provided fields are updated. **Required scope:** `write_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const variant = await client.products.variants.update('prod_86Rf07xd4z', 'variant_k5nR8xLq', { sku: 'UPDATED-SKU', stock_items: [ { stock_location_id: 'sloc_UkLWZg9DAJ', count_on_hand: 75 }, ], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: product_id in: path required: true description: Product ID schema: type: string - name: id in: path required: true description: Variant ID schema: type: string responses: '200': description: variant updated content: application/json: example: id: variant_gbHJdmfrXB product_id: prod_UkLWZg9DAJ sku: UPDATED-SKU options_text: 'Size: S' track_inventory: true media_count: 0 thumbnail_url: purchasable: true in_stock: false backorderable: true weight: 30.56 height: 40.97 width: 164.18 depth: 171.93 price: id: price_gbHJdmfrXB amount: '19.99' amount_in_cents: 1999 compare_at_amount: compare_at_amount_in_cents: currency: USD display_amount: "$19.99" display_compare_at_amount: price_list_id: original_price: option_values: - id: optval_UkLWZg9DAJ option_type_id: opt_UkLWZg9DAJ name: size-24 label: S position: 1 color_code: option_type_name: foo-size-33 option_type_label: Size image_url: metadata: {} created_at: '2026-06-12T17:25:22.723Z' updated_at: '2026-06-12T17:25:22.723Z' metadata: {} position: 2 cost_price: '17.0' cost_currency: USD barcode: weight_unit: lb dimensions_unit: deleted_at: created_at: '2026-06-12T17:25:22.720Z' updated_at: '2026-06-12T17:25:23.019Z' tax_category_id: taxcat_UkLWZg9DAJ available_stock: 0 reserved_quantity: 0 total_on_hand: 0 product_name: Product 845657 requestBody: content: application/json: schema: type: object properties: sku: type: string example: SKU-001 price: type: number example: 29.99 compare_at_price: type: number example: 39.99 cost_price: type: number example: 10.0 cost_currency: type: string example: USD weight: type: number height: type: number width: type: number depth: type: number weight_unit: type: string dimensions_unit: type: string track_inventory: type: boolean tax_category_id: type: string options: type: array items: type: object properties: name: type: string example: Size value: type: string example: Large total_on_hand: type: integer example: 100 position: type: integer barcode: type: string prices: type: array items: type: object properties: currency: type: string example: USD amount: type: number example: 29.99 compare_at_amount: type: number example: 39.99 required: - currency - amount stock_items: type: array items: type: object properties: stock_location_id: type: string count_on_hand: type: integer backorderable: type: boolean delete: summary: Delete a variant tags: - Variants security: - api_key: [] bearer_auth: [] description: |- Soft-deletes a variant. **Required scope:** `write_products` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.products.variants.delete('prod_86Rf07xd4z', 'variant_k5nR8xLq') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: product_id in: path required: true description: Product ID schema: type: string - name: id in: path required: true description: Variant ID schema: type: string responses: '204': description: variant deleted "/api/v3/admin/webhook_endpoints/{webhook_endpoint_id}/deliveries": parameters: - name: webhook_endpoint_id in: path required: true description: Parent webhook endpoint ID schema: type: string get: summary: List webhook deliveries tags: - Webhooks security: - api_key: [] bearer_auth: [] description: |- Returns delivery attempts for the given endpoint, most recent first. Each row carries the original request payload, the response code (when the receiver replied), the execution time, and any transport error — everything needed to audit failures and decide whether to redeliver. **Required scope:** `read_webhooks` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const deliveries = await client.webhookEndpoints.deliveries.list('whe_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: page in: query required: false description: Page number schema: type: integer - name: limit in: query required: false description: Number of records per page schema: type: integer - name: q[event_name_eq] in: query required: false description: Filter by event name (exact) schema: type: string - name: q[success_eq] in: query required: false description: Filter by success flag schema: type: boolean - name: sort in: query required: false description: Sort by field. Prefix with `-` for descending (e.g., `-delivered_at`). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include. id is always included. schema: type: string responses: '200': description: deliveries found content: application/json: example: data: - id: whd_gbHJdmfrXB event_name: order.created event_id: response_code: 500 execution_time: 200 error_type: request_errors: response_body: success: false payload: event: order.created data: id: 1 created_at: '2026-06-12T17:25:23.426Z' updated_at: '2026-06-12T17:25:23.426Z' delivered_at: '2026-06-12T17:25:23.425Z' webhook_endpoint_id: whe_UkLWZg9DAJ webhook_endpoint_url: https://shop.example.com/webhooks - id: whd_UkLWZg9DAJ event_name: order.created event_id: response_code: 200 execution_time: 150 error_type: request_errors: response_body: success: true payload: event: order.created data: id: 1 created_at: '2026-06-12T17:25:23.425Z' updated_at: '2026-06-12T17:25:23.425Z' delivered_at: '2026-06-12T17:25:23.425Z' webhook_endpoint_id: whe_UkLWZg9DAJ webhook_endpoint_url: https://shop.example.com/webhooks meta: page: 1 limit: 25 count: 2 pages: 1 from: 1 to: 2 in: 2 previous: next: '404': description: parent webhook endpoint not found content: application/json: example: error: code: record_not_found message: Webhook endpoint not found schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v3/admin/webhook_endpoints/{webhook_endpoint_id}/deliveries/{id}": parameters: - name: webhook_endpoint_id in: path required: true description: Parent webhook endpoint ID schema: type: string - name: id in: path required: true description: Webhook delivery ID schema: type: string get: summary: Get a webhook delivery tags: - Webhooks security: - api_key: [] bearer_auth: [] description: |- Returns a single delivery attempt with the full request payload and the response body the receiver returned. Use this for ad-hoc debug of failed deliveries. **Required scope:** `read_webhooks` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const delivery = await client.webhookEndpoints.deliveries.get('whe_xxx', 'whd_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include. id is always included. schema: type: string responses: '200': description: delivery found content: application/json: example: id: whd_gbHJdmfrXB event_name: order.created event_id: response_code: 500 execution_time: 200 error_type: request_errors: response_body: success: false payload: event: order.created data: id: 1 created_at: '2026-06-12T17:25:24.048Z' updated_at: '2026-06-12T17:25:24.048Z' delivered_at: '2026-06-12T17:25:24.047Z' webhook_endpoint_id: whe_UkLWZg9DAJ webhook_endpoint_url: https://shop.example.com/webhooks '404': description: delivery not found content: application/json: example: error: code: record_not_found message: Webhook delivery not found schema: "$ref": "#/components/schemas/ErrorResponse" "/api/v3/admin/webhook_endpoints/{webhook_endpoint_id}/deliveries/{id}/redeliver": parameters: - name: webhook_endpoint_id in: path required: true description: Parent webhook endpoint ID schema: type: string - name: id in: path required: true description: Webhook delivery ID to redeliver schema: type: string post: summary: Redeliver a webhook delivery tags: - Webhooks security: - api_key: [] bearer_auth: [] description: |- Creates a new delivery row with the same payload + event_name and queues it. The original row is preserved for audit history. **Required scope:** `write_webhooks` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) // Creates a new delivery row with the same payload + event_name and queues // it. The original row is preserved for audit history. const delivery = await client.webhookEndpoints.deliveries.redeliver('whe_xxx', 'whd_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '201': description: redelivery queued content: application/json: example: id: whd_EfhxLZ9ck8 event_name: order.created event_id: response_code: execution_time: error_type: request_errors: response_body: success: payload: event: order.created data: id: 1 created_at: '2026-06-12T17:25:24.972Z' updated_at: '2026-06-12T17:25:24.972Z' delivered_at: webhook_endpoint_id: whe_UkLWZg9DAJ webhook_endpoint_url: https://shop.example.com/webhooks "/api/v3/admin/webhook_endpoints": get: summary: List webhook endpoints tags: - Webhooks security: - api_key: [] bearer_auth: [] description: |- Returns outbound webhook subscriptions for the current store. Each endpoint receives a signed POST when any subscribed event fires. `secret_key` is `null` on list reads — the plaintext is delivered exactly once on create. **Required scope:** `read_webhooks` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const endpoints = await client.webhookEndpoints.list() parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: page in: query required: false description: Page number schema: type: integer - name: limit in: query required: false description: Number of records per page schema: type: integer - name: q[name_cont] in: query required: false description: Filter by name (contains) schema: type: string - name: q[url_cont] in: query required: false description: Filter by URL (contains) schema: type: string - name: sort in: query required: false description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`). schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include. id is always included. schema: type: string responses: '200': description: webhook endpoints found content: application/json: example: data: - id: whe_UkLWZg9DAJ name: Order pipeline url: https://shop.example.com/webhooks/orders active: true subscriptions: - order.created - order.completed - product.created disabled_reason: created_at: '2026-06-12T17:25:24.999Z' updated_at: '2026-06-12T17:25:24.999Z' disabled_at: secret_key: last_delivery_at: recent_delivery_count: 0 recent_failure_count: 0 total_delivery_count: 0 successful_delivery_count: 0 failed_delivery_count: 0 meta: page: 1 limit: 25 count: 1 pages: 1 from: 1 to: 1 in: 1 previous: next: '401': description: unauthorized content: application/json: example: error: code: authentication_required message: Authentication required schema: "$ref": "#/components/schemas/ErrorResponse" post: summary: Create a webhook endpoint tags: - Webhooks security: - api_key: [] bearer_auth: [] description: |- Creates a new outbound webhook subscription. The plaintext `secret_key` is returned **once** in this response — persist it immediately to verify incoming webhook signatures. Subsequent reads return `null` for the secret. Pass an empty `subscriptions` array or omit it to receive every event. **Required scope:** `write_webhooks` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const endpoint = await client.webhookEndpoints.create({ name: 'Order pipeline', url: 'https://example.com/webhooks/orders', active: true, subscriptions: ['order.completed', 'order.canceled'], }) // The plaintext `secret_key` is returned exactly once on create — persist it // immediately so you can verify incoming webhook signatures. Subsequent reads // will return `null`. const signingSecret = endpoint.secret_key parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '201': description: webhook endpoint created — secret_key returned once content: application/json: example: id: whe_gbHJdmfrXB name: CI integration url: https://ci.example.com/webhooks active: true subscriptions: - order.completed disabled_reason: created_at: '2026-06-12T17:25:25.648Z' updated_at: '2026-06-12T17:25:25.648Z' disabled_at: secret_key: 8a8467ba33df1423b334f3f9bf5ebc62677e04ce10ba482b4b6f91ffea2a28e8 last_delivery_at: recent_delivery_count: 0 recent_failure_count: 0 total_delivery_count: 0 successful_delivery_count: 0 failed_delivery_count: 0 '422': description: validation error content: application/json: example: error: code: validation_error message: |- Url Translation missing. Options considered were: - en.activerecord.errors.models.spree/webhook_endpoint.attributes.url.invalid_url - en.activerecord.errors.models.spree/webhook_endpoint.invalid_url - en.activerecord.errors.messages.invalid_url - en.errors.attributes.url.invalid_url - en.errors.messages.invalid_url details: url: - |- Translation missing. Options considered were: - en.activerecord.errors.models.spree/webhook_endpoint.attributes.url.invalid_url - en.activerecord.errors.models.spree/webhook_endpoint.invalid_url - en.activerecord.errors.messages.invalid_url - en.errors.attributes.url.invalid_url - en.errors.messages.invalid_url schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object required: - url properties: name: type: string example: Order pipeline url: type: string example: https://example.com/webhooks/orders active: type: boolean example: true subscriptions: type: array items: type: string example: - order.completed - order.canceled "/api/v3/admin/webhook_endpoints/{id}": parameters: - name: id in: path required: true description: Webhook endpoint ID schema: type: string get: summary: Get a webhook endpoint tags: - Webhooks security: - api_key: [] bearer_auth: [] description: |- Returns a single webhook endpoint by prefixed ID. **Required scope:** `read_webhooks` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const endpoint = await client.webhookEndpoints.get('whe_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string - name: fields in: query required: false description: Comma-separated list of fields to include. id is always included. schema: type: string responses: '200': description: webhook endpoint found content: application/json: example: id: whe_UkLWZg9DAJ name: Order pipeline url: https://shop.example.com/webhooks/orders active: true subscriptions: - order.created - order.completed - product.created disabled_reason: created_at: '2026-06-12T17:25:26.005Z' updated_at: '2026-06-12T17:25:26.005Z' disabled_at: secret_key: last_delivery_at: recent_delivery_count: 0 recent_failure_count: 0 total_delivery_count: 0 successful_delivery_count: 0 failed_delivery_count: 0 '404': description: webhook endpoint not found content: application/json: example: error: code: record_not_found message: Webhook endpoint not found schema: "$ref": "#/components/schemas/ErrorResponse" patch: summary: Update a webhook endpoint tags: - Webhooks security: - api_key: [] bearer_auth: [] description: |- Updates name, URL, active flag, or the event subscription list. Toggling `active` here is equivalent to calling `disable`/`enable` without an audit reason. **Required scope:** `write_webhooks` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) const endpoint = await client.webhookEndpoints.update('whe_xxx', { name: 'Order pipeline (v2)', subscriptions: ['order.completed', 'order.canceled', 'order.paid'], }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '200': description: webhook endpoint updated content: application/json: example: id: whe_UkLWZg9DAJ name: Order pipeline (renamed) url: https://shop.example.com/webhooks/orders active: true subscriptions: - order.created - order.completed - product.created disabled_reason: created_at: '2026-06-12T17:25:26.680Z' updated_at: '2026-06-12T17:25:26.975Z' disabled_at: secret_key: last_delivery_at: recent_delivery_count: 0 recent_failure_count: 0 total_delivery_count: 0 successful_delivery_count: 0 failed_delivery_count: 0 '422': description: validation error content: application/json: example: error: code: validation_error message: |- Url Translation missing. Options considered were: - en.activerecord.errors.models.spree/webhook_endpoint.attributes.url.invalid_url - en.activerecord.errors.models.spree/webhook_endpoint.invalid_url - en.activerecord.errors.messages.invalid_url - en.errors.attributes.url.invalid_url - en.errors.messages.invalid_url details: url: - |- Translation missing. Options considered were: - en.activerecord.errors.models.spree/webhook_endpoint.attributes.url.invalid_url - en.activerecord.errors.models.spree/webhook_endpoint.invalid_url - en.activerecord.errors.messages.invalid_url - en.errors.attributes.url.invalid_url - en.errors.messages.invalid_url schema: "$ref": "#/components/schemas/ErrorResponse" requestBody: content: application/json: schema: type: object properties: name: type: string url: type: string active: type: boolean subscriptions: type: array items: type: string delete: summary: Delete a webhook endpoint tags: - Webhooks security: - api_key: [] bearer_auth: [] description: |- Soft-deletes the endpoint and stops future deliveries. **Required scope:** `write_webhooks` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) await client.webhookEndpoints.delete('whe_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '204': description: webhook endpoint deleted "/api/v3/admin/webhook_endpoints/{id}/send_test": parameters: - name: id in: path required: true description: Webhook endpoint ID schema: type: string post: summary: Send a test delivery tags: - Webhooks security: - api_key: [] bearer_auth: [] description: |- Creates a `webhook.test` delivery record and queues it. Use this to verify the endpoint is reachable and your signature verification accepts Spree's payloads. **Required scope:** `write_webhooks` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) // Fires a synthetic `webhook.test` delivery so you can verify the endpoint is // reachable and your signature-verification code accepts Spree's payloads. const delivery = await client.webhookEndpoints.sendTest('whe_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '201': description: test delivery queued content: application/json: example: id: whd_UkLWZg9DAJ event_name: webhook.test event_id: response_code: execution_time: error_type: request_errors: response_body: success: payload: id: 8a7131d4-3cd4-45cd-aa0e-673f1905126c name: webhook.test created_at: '2026-06-12T17:25:27Z' data: message: This is a test webhook from Spree. metadata: spree_version: 5.5.0.rc1 created_at: '2026-06-12T17:25:27.972Z' updated_at: '2026-06-12T17:25:27.972Z' delivered_at: webhook_endpoint_id: whe_UkLWZg9DAJ webhook_endpoint_url: https://shop.example.com/webhooks/orders "/api/v3/admin/webhook_endpoints/{id}/enable": parameters: - name: id in: path required: true description: Webhook endpoint ID schema: type: string patch: summary: Re-enable a webhook endpoint tags: - Webhooks security: - api_key: [] bearer_auth: [] description: |- Re-enables an endpoint that was manually or automatically disabled. **Required scope:** `write_webhooks` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) // Re-enable an endpoint that was auto-disabled after repeated delivery failures. const endpoint = await client.webhookEndpoints.enable('whe_xxx') parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '200': description: webhook endpoint enabled content: application/json: example: id: whe_UkLWZg9DAJ name: Order pipeline url: https://shop.example.com/webhooks/orders active: true subscriptions: - order.created - order.completed - product.created disabled_reason: created_at: '2026-06-12T17:25:28.003Z' updated_at: '2026-06-12T17:25:28.309Z' disabled_at: secret_key: last_delivery_at: recent_delivery_count: 0 recent_failure_count: 0 total_delivery_count: 0 successful_delivery_count: 0 failed_delivery_count: 0 "/api/v3/admin/webhook_endpoints/{id}/disable": parameters: - name: id in: path required: true description: Webhook endpoint ID schema: type: string patch: summary: Disable a webhook endpoint tags: - Webhooks security: - api_key: [] bearer_auth: [] description: |- Manually pauses an endpoint. Unlike auto-disable (triggered after repeated delivery failures), no notification email is sent. **Required scope:** `write_webhooks` (for API-key authentication). x-codeSamples: - lang: javascript label: Spree Admin SDK source: |- import { createAdminClient } from '@spree/admin-sdk' const client = createAdminClient({ baseUrl: 'https://your-store.com', secretKey: 'sk_xxx', }) // Pause an endpoint without deleting it. The optional `reason` is shown next // to the disabled indicator in the admin. const endpoint = await client.webhookEndpoints.disable('whe_xxx', { reason: 'Investigating elevated 5xx rate', }) parameters: - name: x-spree-api-key in: header required: true schema: type: string - name: Authorization in: header required: true description: Bearer token for admin authentication schema: type: string responses: '200': description: webhook endpoint disabled content: application/json: example: id: whe_UkLWZg9DAJ name: Order pipeline url: https://shop.example.com/webhooks/orders active: false subscriptions: - order.created - order.completed - product.created disabled_reason: Investigating created_at: '2026-06-12T17:25:28.340Z' updated_at: '2026-06-12T17:25:28.632Z' disabled_at: '2026-06-12T17:25:28.632Z' secret_key: last_delivery_at: recent_delivery_count: 0 recent_failure_count: 0 total_delivery_count: 0 successful_delivery_count: 0 failed_delivery_count: 0 requestBody: content: application/json: schema: type: object properties: reason: type: string example: Investigating elevated 5xx rate servers: - url: http://{defaultHost} variables: defaultHost: default: localhost:3000 tags: - name: Authentication description: Admin user login, logout, token refresh, and current user profile - name: Allowed Origins description: CORS allowlist for storefront and admin client origins - name: API Keys description: Secret and publishable API keys - name: Channels description: Sales channels and product publication across channels - name: Custom Fields description: Custom field definitions for products, variants, customers, and other resources - name: Customer Groups description: Customer groups for segmenting customers (e.g. wholesale, VIP) used by pricing and promotions - name: Customers description: Customer profiles, addresses, credit cards, and store credits - name: Exports description: Async CSV exports of admin resources - name: Fulfillments description: Order fulfillments — shipments, fulfill, cancel, resume, split - name: Gift Cards description: Gift cards and gift card batches - name: Markets description: Markets — geographic groupings of countries used for pricing, tax, and fulfillment rules - name: Option Types description: Option types and option values used to build product variants (e.g. Size, Color) - name: Orders description: Orders, order items, applied gift cards, and applied store credits - name: Payment Methods description: Configured payment providers and their available types - name: Payments description: Order payments — list, capture, void - name: Pricing description: Prices and price lists for currency-, market-, and customer-group-specific pricing - name: Products description: Products, taxons/categories, product custom field values, and bulk product operations - name: Promotions description: Promotions, promotion rules, promotion actions, and coupon codes - name: Refunds description: Order refunds - name: Settings description: Store-level settings — store profile, tags, store credit categories - name: Staff description: Admin users, roles, and invitations to the store - name: Stock Locations description: Warehouses and physical fulfillment locations - name: Variants description: Product variants — the individual SKUs (size/color combinations) sold under a product - name: Webhooks description: Webhook endpoints and webhook delivery history x-tagGroups: - name: Authentication tags: - Authentication - name: Products & Catalog tags: - Products - Variants - Option Types - Custom Fields - Channels - name: Pricing tags: - Pricing - Markets - name: Orders & Fulfillment tags: - Orders - Payments - Fulfillments - Refunds - name: Customers tags: - Customers - Customer Groups - name: Promotions & Gift Cards tags: - Promotions - Gift Cards - name: Data tags: - Exports - name: Configuration tags: - Settings - Stock Locations - Payment Methods - Staff - API Keys - Allowed Origins - Webhooks components: securitySchemes: api_key: type: apiKey name: x-spree-api-key in: header description: Secret API key for admin access bearer_auth: type: http scheme: bearer bearerFormat: JWT description: JWT token for admin user authentication schemas: PaginationMeta: type: object properties: page: type: integer example: 1 limit: type: integer example: 25 count: type: integer example: 100 description: Total number of records pages: type: integer example: 4 description: Total number of pages from: type: integer example: 1 description: Index of first record on this page to: type: integer example: 25 description: Index of last record on this page in: type: integer example: 25 description: Number of records on this page previous: type: integer nullable: true example: description: Previous page number next: type: integer nullable: true example: 2 description: Next page number required: - page - limit - count - pages - from - to - in ErrorResponse: type: object properties: error: type: object properties: code: type: string example: record_not_found message: type: string example: Record not found details: type: object description: Field-specific validation errors nullable: true example: name: - is too short - is required email: - is invalid required: - code - message required: - error example: error: code: validation_error message: Validation failed details: name: - is too short email: - is invalid AuthResponse: type: object properties: token: type: string description: JWT access token user: "$ref": "#/components/schemas/AdminUser" required: - token - user PermissionRule: type: object description: A single permission rule (CanCanCan rule). Rules are applied in order, last-matching-wins. properties: allow: type: boolean description: true for `can`, false for `cannot` actions: type: array items: type: string description: Action names, e.g. ["read", "update"] or ["manage"] subjects: type: array items: type: string description: Subject class names, e.g. ["Spree::Product"] or ["all"] has_conditions: type: boolean description: True if the server-side rule has per-record conditions. The SPA shows the action optimistically and handles 403 from the API. required: - allow - actions - subjects - has_conditions MeResponse: type: object description: Current admin user profile and serialized permissions properties: user: "$ref": "#/components/schemas/AdminUser" permissions: type: array items: "$ref": "#/components/schemas/PermissionRule" required: - user - permissions CheckoutRequirement: type: object properties: step: type: string description: Checkout step this requirement belongs to example: payment field: type: string description: Field that needs to be satisfied example: payment message: type: string description: Human-readable requirement message example: Add a payment method required: - step - field - message CartWarning: type: object description: A warning about a cart issue (e.g., item removed due to stock change) properties: code: type: string description: Machine-readable warning code example: line_item_removed message: type: string description: Human-readable warning message example: Blue T-Shirt was removed because it was sold out line_item_id: type: string nullable: true description: Prefixed line item ID (when applicable) example: li_abc123 variant_id: type: string nullable: true description: Prefixed variant ID (when applicable) example: variant_abc123 required: - code - message FulfillmentManifestItem: type: object description: An item within a fulfillment — which line item and how many units are in this fulfillment properties: item_id: type: string description: Line item ID example: li_abc123 variant_id: type: string description: Variant ID example: variant_abc123 quantity: type: integer description: Quantity in this fulfillment example: 2 required: - item_id - variant_id - quantity AdminUserRoleAssignment: type: object description: A role assignment for the current store on a staff member properties: id: type: string description: Prefixed role ID example: role_abc123 name: type: string description: Role name example: admin required: - id - name PreferenceField: type: object description: A single configurable preference on a payment method, promotion rule/action, or calculator. The frontend uses `type` + `default` to render a sensible input. properties: key: type: string example: amount_min type: type: string example: decimal description: string | text | password | integer | decimal | boolean | array | hash default: description: Default value (any JSON type), null when there is no default nullable: true required: - key - type PromotionActionCalculator: type: object description: The action's nested calculator (when the action carries one — null for actions like `free_shipping`) properties: type: type: string example: flat_rate description: Wire shorthand for the calculator subclass label: type: string example: Flat Rate preferences: type: object additionalProperties: true preference_schema: type: array items: "$ref": "#/components/schemas/PreferenceField" required: - type - label - preferences - preference_schema PromotionActionLineItem: type: object description: One row in a `create_line_items` action — the variant added to the order and how many properties: variant_id: type: string example: variant_abc123 quantity: type: integer example: 1 required: - variant_id - quantity Address: type: object properties: id: type: string first_name: type: string nullable: true last_name: type: string nullable: true full_name: type: string address1: type: string nullable: true address2: type: string nullable: true postal_code: type: string nullable: true city: type: string nullable: true phone: type: string nullable: true company: type: string nullable: true country_name: type: string country_iso: type: string state_text: type: string nullable: true state_abbr: type: string nullable: true quick_checkout: type: boolean is_default_billing: type: boolean is_default_shipping: type: boolean state_name: type: string nullable: true label: type: string nullable: true metadata: type: object created_at: type: string updated_at: type: string customer_id: type: string nullable: true required: - id - first_name - last_name - full_name - address1 - address2 - postal_code - city - phone - company - country_name - country_iso - state_text - state_abbr - quick_checkout - is_default_billing - is_default_shipping - state_name - label - metadata - created_at - updated_at - customer_id x-typelizer: true Adjustment: type: object properties: id: type: string label: type: string display_amount: type: string included: type: boolean created_at: type: string updated_at: type: string amount: type: string order_id: type: string nullable: true required: - id - label - display_amount - included - created_at - updated_at - amount - order_id x-typelizer: true AdminUser: type: object properties: id: type: string email: type: string first_name: type: string nullable: true last_name: type: string nullable: true full_name: type: string nullable: true created_at: type: string updated_at: type: string roles: type: array items: "$ref": "#/components/schemas/AdminUserRoleAssignment" required: - id - email - first_name - last_name - full_name - created_at - updated_at - roles x-typelizer: true AllowedOrigin: type: object properties: id: type: string origin: type: string created_at: type: string updated_at: type: string required: - id - origin - created_at - updated_at x-typelizer: true ApiKey: type: object properties: id: type: string name: type: string key_type: type: string token_prefix: type: string nullable: true scopes: type: array items: type: string created_at: type: string updated_at: type: string revoked_at: type: string nullable: true last_used_at: type: string nullable: true plaintext_token: type: string nullable: true created_by_email: type: string nullable: true required: - id - name - key_type - token_prefix - scopes - created_at - updated_at - revoked_at - last_used_at - plaintext_token - created_by_email x-typelizer: true Category: type: object properties: id: type: string name: type: string permalink: type: string position: type: number depth: type: number meta_title: type: string nullable: true meta_description: type: string nullable: true meta_keywords: type: string nullable: true children_count: type: number parent_id: type: string nullable: true description: type: string description_html: type: string image_url: type: string nullable: true square_image_url: type: string nullable: true is_root: type: boolean is_child: type: boolean is_leaf: type: boolean parent: "$ref": "#/components/schemas/Category" children: type: array items: "$ref": "#/components/schemas/Category" ancestors: type: array items: "$ref": "#/components/schemas/Category" custom_fields: type: array items: "$ref": "#/components/schemas/CustomField" metadata: type: object pretty_name: type: string lft: type: number rgt: type: number created_at: type: string updated_at: type: string required: - id - name - permalink - position - depth - meta_title - meta_description - meta_keywords - children_count - parent_id - description - description_html - image_url - square_image_url - is_root - is_child - is_leaf - metadata - pretty_name - lft - rgt - created_at - updated_at x-typelizer: true Channel: type: object properties: id: type: string name: type: string code: type: string active: type: boolean default: type: boolean preferred_order_routing_strategy: type: string nullable: true created_at: type: string updated_at: type: string required: - id - name - code - active - default - preferred_order_routing_strategy - created_at - updated_at x-typelizer: true Country: type: object properties: iso: type: string iso3: type: string name: type: string states_required: type: boolean zipcode_required: type: boolean states: type: array items: "$ref": "#/components/schemas/State" market: allOf: - "$ref": "#/components/schemas/Market" nullable: true created_at: type: object updated_at: type: object required: - iso - iso3 - name - states_required - zipcode_required - created_at - updated_at x-typelizer: true CouponCode: type: object properties: id: type: string code: type: string state: type: string nullable: true created_at: type: string updated_at: type: string promotion_id: type: string order_id: type: string nullable: true required: - id - code - state - created_at - updated_at - promotion_id - order_id x-typelizer: true CreditCard: type: object properties: id: type: string brand: type: string last4: type: string month: type: number year: type: number name: type: string nullable: true default: type: boolean gateway_payment_profile_id: type: string nullable: true customer_id: type: string nullable: true payment_method_id: type: string nullable: true metadata: type: object created_at: type: string updated_at: type: string required: - id - brand - last4 - month - year - name - default - gateway_payment_profile_id - customer_id - payment_method_id - metadata - created_at - updated_at x-typelizer: true CustomFieldDefinition: type: object properties: id: type: string namespace: type: string key: type: string label: type: string field_type: type: string enum: - short_text - long_text - rich_text - number - boolean - json resource_type: type: string storefront_visible: type: boolean created_at: type: string updated_at: type: string required: - id - namespace - key - label - field_type - resource_type - storefront_visible - created_at - updated_at x-typelizer: true CustomField: type: object properties: id: type: string label: type: string type: type: string deprecated: true field_type: type: string enum: - short_text - long_text - rich_text - number - boolean - json key: type: string value: type: object created_at: type: string updated_at: type: string storefront_visible: type: boolean custom_field_definition_id: type: string required: - id - label - type - field_type - key - value - created_at - updated_at - storefront_visible - custom_field_definition_id x-typelizer: true CustomerGroup: type: object properties: id: type: string name: type: string description: type: string nullable: true customers_count: type: number created_at: type: string updated_at: type: string customers: type: array items: "$ref": "#/components/schemas/Customer" required: - id - name - description - customers_count - created_at - updated_at x-typelizer: true Customer: type: object properties: id: type: string email: type: string first_name: type: string nullable: true last_name: type: string nullable: true phone: type: string nullable: true accepts_email_marketing: type: boolean full_name: type: string available_store_credit_total: type: string display_available_store_credit_total: type: string addresses: type: array items: "$ref": "#/components/schemas/Address" default_billing_address: allOf: - "$ref": "#/components/schemas/Address" nullable: true default_shipping_address: allOf: - "$ref": "#/components/schemas/Address" nullable: true login: type: string nullable: true metadata: type: object last_sign_in_at: type: string nullable: true current_sign_in_at: type: string nullable: true created_at: type: string updated_at: type: string sign_in_count: type: number failed_attempts: type: number last_sign_in_ip: type: string nullable: true current_sign_in_ip: type: string nullable: true tags: type: array items: type: string internal_note_html: type: string nullable: true default_billing_address_id: type: string nullable: true default_shipping_address_id: type: string nullable: true orders_count: type: number total_spent: type: string display_total_spent: type: string last_order_completed_at: type: string nullable: true orders: type: array items: "$ref": "#/components/schemas/Order" store_credits: type: array items: "$ref": "#/components/schemas/StoreCredit" customer_groups: type: array items: "$ref": "#/components/schemas/CustomerGroup" required: - id - email - first_name - last_name - phone - accepts_email_marketing - full_name - available_store_credit_total - display_available_store_credit_total - login - metadata - last_sign_in_at - current_sign_in_at - created_at - updated_at - sign_in_count - failed_attempts - last_sign_in_ip - current_sign_in_ip - tags - internal_note_html - default_billing_address_id - default_shipping_address_id - orders_count - total_spent - display_total_spent - last_order_completed_at x-typelizer: true DeliveryMethod: type: object properties: id: type: string name: type: string code: type: string nullable: true created_at: type: string updated_at: type: string required: - id - name - code - created_at - updated_at x-typelizer: true DeliveryRate: type: object properties: id: type: string delivery_method_id: type: string name: type: string selected: type: boolean cost: type: string total: type: string additional_tax_total: type: string included_tax_total: type: string tax_total: type: string display_cost: type: string display_total: type: string display_additional_tax_total: type: string display_included_tax_total: type: string display_tax_total: type: string delivery_method: "$ref": "#/components/schemas/DeliveryMethod" created_at: type: string updated_at: type: string required: - id - delivery_method_id - name - selected - cost - total - additional_tax_total - included_tax_total - tax_total - display_cost - display_total - display_additional_tax_total - display_included_tax_total - display_tax_total - created_at - updated_at x-typelizer: true DigitalLink: type: object properties: id: type: string access_counter: type: number filename: type: string content_type: type: string download_url: type: string authorizable: type: boolean expired: type: boolean access_limit_exceeded: type: boolean created_at: type: string updated_at: type: string required: - id - access_counter - filename - content_type - download_url - authorizable - expired - access_limit_exceeded - created_at - updated_at x-typelizer: true Discount: type: object properties: id: type: string promotion_id: type: string name: type: string description: type: string nullable: true code: type: string nullable: true amount: type: string display_amount: type: string created_at: type: string updated_at: type: string required: - id - promotion_id - name - description - code - amount - display_amount - created_at - updated_at x-typelizer: true Export: type: object properties: id: type: string number: type: string type: type: string nullable: true format: type: string nullable: true created_at: type: string updated_at: type: string user_id: type: string nullable: true done: type: boolean filename: type: string nullable: true byte_size: type: number nullable: true download_url: type: string nullable: true required: - id - number - type - format - created_at - updated_at - user_id - done - filename - byte_size - download_url x-typelizer: true Fulfillment: type: object properties: id: type: string number: type: string tracking: type: string nullable: true tracking_url: type: string nullable: true cost: type: string display_cost: type: string total: type: string display_total: type: string discount_total: type: string display_discount_total: type: string additional_tax_total: type: string display_additional_tax_total: type: string included_tax_total: type: string display_included_tax_total: type: string tax_total: type: string display_tax_total: type: string status: type: string fulfillment_type: type: string fulfilled_at: type: string nullable: true items: type: array items: "$ref": "#/components/schemas/FulfillmentManifestItem" delivery_method: "$ref": "#/components/schemas/DeliveryMethod" stock_location: "$ref": "#/components/schemas/StockLocation" delivery_rates: type: array items: "$ref": "#/components/schemas/DeliveryRate" metadata: type: object adjustment_total: type: string pre_tax_amount: type: string created_at: type: string updated_at: type: string order_id: type: string nullable: true stock_location_id: type: string nullable: true order: "$ref": "#/components/schemas/Order" adjustments: type: array items: "$ref": "#/components/schemas/Adjustment" required: - id - number - tracking - tracking_url - cost - display_cost - total - display_total - discount_total - display_discount_total - additional_tax_total - display_additional_tax_total - included_tax_total - display_included_tax_total - tax_total - display_tax_total - status - fulfillment_type - fulfilled_at - items - metadata - adjustment_total - pre_tax_amount - created_at - updated_at - order_id - stock_location_id x-typelizer: true GiftCardBatch: type: object properties: id: type: string codes_count: type: number currency: type: string nullable: true prefix: type: string nullable: true created_at: type: string updated_at: type: string amount: type: string nullable: true expires_at: type: string nullable: true created_by_id: type: string nullable: true required: - id - codes_count - currency - prefix - created_at - updated_at - amount - expires_at - created_by_id x-typelizer: true GiftCard: type: object properties: id: type: string code: type: string status: type: string currency: type: string amount: type: string amount_used: type: string amount_authorized: type: string amount_remaining: type: string display_amount: type: string display_amount_used: type: string display_amount_remaining: type: string expires_at: type: string nullable: true redeemed_at: type: string nullable: true expired: type: boolean active: type: boolean created_at: type: string updated_at: type: string customer_id: type: string nullable: true created_by_id: type: string nullable: true customer: "$ref": "#/components/schemas/Customer" created_by: "$ref": "#/components/schemas/AdminUser" gift_card_batch: "$ref": "#/components/schemas/GiftCardBatch" orders: type: array items: "$ref": "#/components/schemas/Order" required: - id - code - status - currency - amount - amount_used - amount_authorized - amount_remaining - display_amount - display_amount_used - display_amount_remaining - expires_at - redeemed_at - expired - active - created_at - updated_at - customer_id - created_by_id x-typelizer: true Invitation: type: object properties: id: type: string email: type: string status: type: string created_at: type: string updated_at: type: string expires_at: type: string role_id: type: string role_name: type: string inviter_email: type: string acceptance_url: type: string invitee_exists: type: boolean store: type: object required: - id - email - status - created_at - updated_at - expires_at - role_id - role_name - inviter_email - acceptance_url - invitee_exists - store x-typelizer: true LineItem: type: object properties: id: type: string variant_id: type: string quantity: type: number currency: type: string name: type: string slug: type: string options_text: type: string price: type: string display_price: type: string total: type: string display_total: type: string adjustment_total: type: string display_adjustment_total: type: string additional_tax_total: type: string display_additional_tax_total: type: string included_tax_total: type: string display_included_tax_total: type: string discount_total: type: string display_discount_total: type: string pre_tax_amount: type: string display_pre_tax_amount: type: string discounted_amount: type: string display_discounted_amount: type: string display_compare_at_amount: type: string nullable: true compare_at_amount: type: string nullable: true thumbnail_url: type: string nullable: true option_values: type: array items: "$ref": "#/components/schemas/OptionValue" digital_links: type: array items: "$ref": "#/components/schemas/DigitalLink" metadata: type: object created_at: type: string updated_at: type: string cost_price: type: string nullable: true tax_category_id: type: string nullable: true variant: "$ref": "#/components/schemas/Variant" tax_category: "$ref": "#/components/schemas/TaxCategory" adjustments: type: array items: "$ref": "#/components/schemas/Adjustment" required: - id - variant_id - quantity - currency - name - slug - options_text - price - display_price - total - display_total - adjustment_total - display_adjustment_total - additional_tax_total - display_additional_tax_total - included_tax_total - display_included_tax_total - discount_total - display_discount_total - pre_tax_amount - display_pre_tax_amount - discounted_amount - display_discounted_amount - display_compare_at_amount - compare_at_amount - thumbnail_url - option_values - digital_links - metadata - created_at - updated_at - cost_price - tax_category_id x-typelizer: true Market: type: object properties: id: type: string name: type: string currency: type: string default_locale: type: string tax_inclusive: type: boolean default: type: boolean country_isos: type: array items: type: string supported_locales: type: array items: type: string countries: type: array items: "$ref": "#/components/schemas/Country" created_at: type: string updated_at: type: string required: - id - name - currency - default_locale - tax_inclusive - default - country_isos - supported_locales - created_at - updated_at x-typelizer: true Media: type: object properties: id: type: string product_id: type: string nullable: true variant_ids: type: array items: type: string position: type: number alt: type: string nullable: true media_type: type: string focal_point_x: type: number nullable: true focal_point_y: type: number nullable: true external_video_url: type: string nullable: true original_url: type: string nullable: true mini_url: type: string nullable: true small_url: type: string nullable: true medium_url: type: string nullable: true large_url: type: string nullable: true xlarge_url: type: string nullable: true og_image_url: type: string nullable: true created_at: type: string updated_at: type: string viewable_id: type: string download_url: type: string nullable: true metadata: type: object viewable_type: type: string required: - id - product_id - variant_ids - position - alt - media_type - focal_point_x - focal_point_y - external_video_url - original_url - mini_url - small_url - medium_url - large_url - xlarge_url - og_image_url - created_at - updated_at - viewable_id - download_url - metadata - viewable_type x-typelizer: true OptionType: type: object properties: id: type: string name: type: string label: type: string position: type: number kind: type: string metadata: type: object filterable: type: boolean created_at: type: string updated_at: type: string option_values: type: array items: "$ref": "#/components/schemas/OptionValue" required: - id - name - label - position - kind - metadata - filterable - created_at - updated_at x-typelizer: true OptionValue: type: object properties: id: type: string option_type_id: type: string name: type: string label: type: string position: type: number color_code: type: string nullable: true option_type_name: type: string option_type_label: type: string image_url: type: string nullable: true metadata: type: object created_at: type: string updated_at: type: string option_type: "$ref": "#/components/schemas/OptionType" required: - id - option_type_id - name - label - position - color_code - option_type_name - option_type_label - image_url - metadata - created_at - updated_at x-typelizer: true Order: type: object properties: id: type: string market_id: type: string nullable: true channel_id: type: string nullable: true number: type: string email: type: string customer_note: type: string nullable: true currency: type: string locale: type: string nullable: true total_quantity: type: number item_total: type: string display_item_total: type: string adjustment_total: type: string display_adjustment_total: type: string discount_total: type: string display_discount_total: type: string tax_total: type: string display_tax_total: type: string included_tax_total: type: string display_included_tax_total: type: string additional_tax_total: type: string display_additional_tax_total: type: string total: type: string display_total: type: string gift_card_total: type: string display_gift_card_total: type: string amount_due: type: string display_amount_due: type: string delivery_total: type: string display_delivery_total: type: string fulfillment_status: type: string nullable: true payment_status: type: string nullable: true completed_at: type: string nullable: true store_credit_total: type: string display_store_credit_total: type: string covered_by_store_credit: type: boolean discounts: type: array items: "$ref": "#/components/schemas/Discount" items: type: array items: "$ref": "#/components/schemas/LineItem" fulfillments: type: array items: "$ref": "#/components/schemas/Fulfillment" payments: type: array items: "$ref": "#/components/schemas/Payment" billing_address: allOf: - "$ref": "#/components/schemas/Address" nullable: true shipping_address: allOf: - "$ref": "#/components/schemas/Address" nullable: true gift_card: allOf: - "$ref": "#/components/schemas/GiftCard" nullable: true market: allOf: - "$ref": "#/components/schemas/Market" nullable: true status: type: string last_ip_address: type: string nullable: true considered_risky: type: boolean confirmation_delivered: type: boolean store_owner_notification_delivered: type: boolean payment_total: type: string display_payment_total: type: string metadata: type: object canceled_at: type: string nullable: true approved_at: type: string nullable: true created_at: type: string updated_at: type: string preferred_stock_location_id: type: string nullable: true tags: type: array items: type: string internal_note: type: string nullable: true approver_id: type: string nullable: true canceler_id: type: string nullable: true created_by_id: type: string nullable: true customer_id: type: string nullable: true channel: "$ref": "#/components/schemas/Channel" preferred_stock_location: "$ref": "#/components/schemas/StockLocation" payment_methods: type: array items: "$ref": "#/components/schemas/PaymentMethod" customer: "$ref": "#/components/schemas/Customer" approver: "$ref": "#/components/schemas/Customer" canceler: "$ref": "#/components/schemas/Customer" created_by: "$ref": "#/components/schemas/Customer" adjustments: type: array items: "$ref": "#/components/schemas/Adjustment" return_authorizations: type: array items: "$ref": "#/components/schemas/ReturnAuthorization" reimbursements: type: array items: "$ref": "#/components/schemas/Reimbursement" required: - id - market_id - channel_id - number - email - customer_note - currency - locale - total_quantity - item_total - display_item_total - adjustment_total - display_adjustment_total - discount_total - display_discount_total - tax_total - display_tax_total - included_tax_total - display_included_tax_total - additional_tax_total - display_additional_tax_total - total - display_total - gift_card_total - display_gift_card_total - amount_due - display_amount_due - delivery_total - display_delivery_total - fulfillment_status - payment_status - completed_at - store_credit_total - display_store_credit_total - covered_by_store_credit - gift_card - market - status - last_ip_address - considered_risky - confirmation_delivered - store_owner_notification_delivered - payment_total - display_payment_total - metadata - canceled_at - approved_at - created_at - updated_at - preferred_stock_location_id - tags - internal_note - approver_id - canceler_id - created_by_id - customer_id x-typelizer: true PaymentMethod: type: object properties: id: type: string name: type: string description: type: string nullable: true type: type: string session_required: type: boolean source_required: type: boolean metadata: type: object active: type: boolean auto_capture: type: boolean nullable: true storefront_visible: type: boolean position: type: number created_at: type: string updated_at: type: string preferences: type: object preference_schema: type: object required: - id - name - description - type - session_required - source_required - metadata - active - auto_capture - storefront_visible - position - created_at - updated_at - preferences - preference_schema x-typelizer: true Payment: type: object properties: id: type: string payment_method_id: type: string response_code: type: string nullable: true number: type: string amount: type: string display_amount: type: string status: type: string source_type: type: string nullable: true enum: - credit_card - store_credit - payment_source source_id: type: string nullable: true source: anyOf: - "$ref": "#/components/schemas/CreditCard" - "$ref": "#/components/schemas/StoreCredit" - "$ref": "#/components/schemas/PaymentSource" nullable: true payment_method: "$ref": "#/components/schemas/PaymentMethod" metadata: type: object avs_response: type: string nullable: true cvv_response_code: type: string nullable: true cvv_response_message: type: string nullable: true created_at: type: string updated_at: type: string captured_amount: type: string order_id: type: string nullable: true order: "$ref": "#/components/schemas/Order" refunds: type: array items: "$ref": "#/components/schemas/Refund" required: - id - payment_method_id - response_code - number - amount - display_amount - status - source_type - source_id - source - metadata - avs_response - cvv_response_code - cvv_response_message - created_at - updated_at - captured_amount - order_id x-typelizer: true PaymentSource: type: object properties: id: type: string gateway_payment_profile_id: type: string nullable: true metadata: type: object created_at: type: string updated_at: type: string required: - id - gateway_payment_profile_id - metadata - created_at - updated_at x-typelizer: true PriceHistory: type: object properties: id: type: string amount: type: string amount_in_cents: type: number currency: type: string display_amount: type: string recorded_at: type: string variant_id: type: string price_id: type: string compare_at_amount: type: string nullable: true created_at: type: string required: - id - amount - amount_in_cents - currency - display_amount - recorded_at - variant_id - price_id - compare_at_amount - created_at x-typelizer: true PriceList: type: object properties: id: type: string name: type: string description: type: string nullable: true status: type: string position: type: number match_policy: type: string starts_at: type: string nullable: true ends_at: type: string nullable: true deleted_at: type: string nullable: true created_at: type: string updated_at: type: string currently_active: type: boolean products_count: type: number prices_count: type: number product_ids: type: array items: type: string price_rules: type: array items: "$ref": "#/components/schemas/PriceRule" required: - id - name - description - status - position - match_policy - starts_at - ends_at - deleted_at - created_at - updated_at - currently_active - products_count - prices_count - product_ids x-typelizer: true PriceRule: type: object properties: id: type: string created_at: type: string updated_at: type: string type: type: string price_list_id: type: string preferences: type: object preference_schema: type: array items: "$ref": "#/components/schemas/PreferenceField" label: type: string description: type: string nullable: true markets: type: array items: "$ref": "#/components/schemas/Market" customer_groups: type: array items: "$ref": "#/components/schemas/CustomerGroup" customers: type: array items: "$ref": "#/components/schemas/Customer" required: - id - created_at - updated_at - type - price_list_id - preferences - preference_schema - label - description x-typelizer: true Price: type: object properties: id: type: string amount: type: string nullable: true amount_in_cents: type: number nullable: true compare_at_amount: type: string nullable: true compare_at_amount_in_cents: type: number nullable: true currency: type: string nullable: true display_amount: type: string nullable: true display_compare_at_amount: type: string nullable: true price_list_id: type: string nullable: true variant_id: type: string nullable: true created_at: type: string updated_at: type: string variant: "$ref": "#/components/schemas/Variant" required: - id - amount - amount_in_cents - compare_at_amount - compare_at_amount_in_cents - currency - display_amount - display_compare_at_amount - price_list_id - variant_id - created_at - updated_at x-typelizer: true ProductPublication: type: object properties: id: type: string published_at: type: string nullable: true unpublished_at: type: string nullable: true product_id: type: string channel_id: type: string created_at: type: string updated_at: type: string required: - id - published_at - unpublished_at - product_id - channel_id - created_at - updated_at x-typelizer: true Product: type: object properties: id: type: string name: type: string slug: type: string meta_title: type: string nullable: true meta_description: type: string nullable: true meta_keywords: type: string nullable: true variant_count: type: number available_on: type: string nullable: true purchasable: type: boolean in_stock: type: boolean backorderable: type: boolean available: type: boolean description: type: string nullable: true description_html: type: string nullable: true default_variant_id: type: string thumbnail_url: type: string nullable: true tags: type: array items: type: string price: allOf: - "$ref": "#/components/schemas/Price" nullable: true original_price: allOf: - "$ref": "#/components/schemas/Price" nullable: true primary_media: "$ref": "#/components/schemas/Media" media: type: array items: "$ref": "#/components/schemas/Media" variants: type: array items: "$ref": "#/components/schemas/Variant" default_variant: "$ref": "#/components/schemas/Variant" option_types: type: array items: "$ref": "#/components/schemas/OptionType" option_values: type: array items: "$ref": "#/components/schemas/OptionValue" categories: type: array items: "$ref": "#/components/schemas/Category" custom_fields: type: array items: "$ref": "#/components/schemas/CustomField" prior_price: allOf: - "$ref": "#/components/schemas/PriceHistory" nullable: true status: type: string metadata: type: object deleted_at: type: string nullable: true created_at: type: string updated_at: type: string tax_category_id: type: string nullable: true product_publications: type: array items: "$ref": "#/components/schemas/ProductPublication" channels: type: array items: "$ref": "#/components/schemas/Channel" required: - id - name - slug - meta_title - meta_description - meta_keywords - variant_count - available_on - purchasable - in_stock - backorderable - available - description - description_html - default_variant_id - thumbnail_url - tags - price - original_price - status - metadata - deleted_at - created_at - updated_at - tax_category_id x-typelizer: true PromotionAction: type: object properties: id: type: string created_at: type: string updated_at: type: string type: type: string promotion_id: type: string preferences: type: object preference_schema: type: array items: "$ref": "#/components/schemas/PreferenceField" label: type: string calculator: allOf: - "$ref": "#/components/schemas/PromotionActionCalculator" nullable: true line_items: type: array items: "$ref": "#/components/schemas/PromotionActionLineItem" nullable: true required: - id - created_at - updated_at - type - promotion_id - preferences - preference_schema - label - calculator - line_items x-typelizer: true PromotionRule: type: object properties: id: type: string created_at: type: string updated_at: type: string type: type: string promotion_id: type: string preferences: type: object preference_schema: type: array items: "$ref": "#/components/schemas/PreferenceField" label: type: string product_ids: type: array items: type: string nullable: true category_ids: type: array items: type: string nullable: true customer_ids: type: array items: type: string nullable: true products: type: array items: "$ref": "#/components/schemas/Product" categories: type: array items: "$ref": "#/components/schemas/Category" customers: type: array items: "$ref": "#/components/schemas/Customer" customer_groups: type: array items: "$ref": "#/components/schemas/CustomerGroup" countries: type: array items: "$ref": "#/components/schemas/Country" required: - id - created_at - updated_at - type - promotion_id - preferences - preference_schema - label - product_ids - category_ids - customer_ids x-typelizer: true Promotion: type: object properties: id: type: string name: type: string description: type: string nullable: true code: type: string nullable: true starts_at: type: string nullable: true expires_at: type: string nullable: true usage_limit: type: number nullable: true match_policy: type: string enum: - all - any path: type: string nullable: true kind: type: string enum: - coupon_code - automatic multi_codes: type: boolean number_of_codes: type: number nullable: true code_prefix: type: string nullable: true promotion_category_id: type: string nullable: true metadata: type: object created_at: type: string updated_at: type: string action_ids: type: array items: type: string rule_ids: type: array items: type: string required: - id - name - description - code - starts_at - expires_at - usage_limit - match_policy - path - kind - multi_codes - number_of_codes - code_prefix - promotion_category_id - metadata - created_at - updated_at - action_ids - rule_ids x-typelizer: true Refund: type: object properties: id: type: string transaction_id: type: string nullable: true amount: type: string nullable: true payment_id: type: string nullable: true refund_reason_id: type: string nullable: true reimbursement_id: type: string nullable: true metadata: type: object created_at: type: string updated_at: type: string payment: "$ref": "#/components/schemas/Payment" reimbursement: "$ref": "#/components/schemas/Reimbursement" required: - id - transaction_id - amount - payment_id - refund_reason_id - reimbursement_id - metadata - created_at - updated_at x-typelizer: true Reimbursement: type: object properties: id: type: string number: type: string reimbursement_status: type: string nullable: true total: type: string nullable: true order_id: type: string nullable: true customer_return_id: type: string nullable: true created_at: type: string updated_at: type: string order: "$ref": "#/components/schemas/Order" required: - id - number - reimbursement_status - total - order_id - customer_return_id - created_at - updated_at x-typelizer: true ReturnAuthorization: type: object properties: id: type: string number: type: string status: type: string order_id: type: string nullable: true stock_location_id: type: string nullable: true return_authorization_reason_id: type: string nullable: true created_at: type: string updated_at: type: string order: "$ref": "#/components/schemas/Order" stock_location: "$ref": "#/components/schemas/StockLocation" required: - id - number - status - order_id - stock_location_id - return_authorization_reason_id - created_at - updated_at x-typelizer: true Role: type: object properties: id: type: string name: type: string created_at: type: string updated_at: type: string required: - id - name - created_at - updated_at x-typelizer: true State: type: object properties: abbr: type: string name: type: string created_at: type: object updated_at: type: object required: - abbr - name - created_at - updated_at x-typelizer: true StockItem: type: object properties: id: type: string count_on_hand: type: number backorderable: type: boolean stock_location_id: type: string nullable: true variant_id: type: string nullable: true metadata: type: object created_at: type: string updated_at: type: string allocated_count: type: number available_count: type: number stock_location: "$ref": "#/components/schemas/StockLocation" variant: "$ref": "#/components/schemas/Variant" required: - id - count_on_hand - backorderable - stock_location_id - variant_id - metadata - created_at - updated_at - allocated_count - available_count x-typelizer: true StockLocation: type: object properties: id: type: string state_abbr: type: string nullable: true name: type: string address1: type: string nullable: true city: type: string nullable: true zipcode: type: string nullable: true country_iso: type: string nullable: true country_name: type: string nullable: true state_text: type: string nullable: true admin_name: type: string nullable: true address2: type: string nullable: true state_name: type: string nullable: true phone: type: string nullable: true company: type: string nullable: true active: type: boolean default: type: boolean backorderable_default: type: boolean propagate_all_variants: type: boolean kind: type: string pickup_enabled: type: boolean pickup_stock_policy: type: string pickup_ready_in_minutes: type: number nullable: true pickup_instructions: type: string nullable: true created_at: type: string updated_at: type: string required: - id - state_abbr - name - address1 - city - zipcode - country_iso - country_name - state_text - admin_name - address2 - state_name - phone - company - active - default - backorderable_default - propagate_all_variants - kind - pickup_enabled - pickup_stock_policy - pickup_ready_in_minutes - pickup_instructions - created_at - updated_at x-typelizer: true StockReservation: type: object properties: id: type: string stock_item_id: type: string line_item_id: type: string order_id: type: string variant_id: type: string nullable: true stock_location_id: type: string nullable: true quantity: type: number expires_at: type: string active: type: boolean created_at: type: string updated_at: type: string required: - id - stock_item_id - line_item_id - order_id - variant_id - stock_location_id - quantity - expires_at - active - created_at - updated_at x-typelizer: true StockTransfer: type: object properties: id: type: string number: type: string reference: type: string nullable: true metadata: type: object created_at: type: string updated_at: type: string source_location_id: type: string nullable: true destination_location_id: type: string nullable: true source_location: "$ref": "#/components/schemas/StockLocation" destination_location: "$ref": "#/components/schemas/StockLocation" required: - id - number - reference - metadata - created_at - updated_at - source_location_id - destination_location_id x-typelizer: true StoreCreditCategory: type: object properties: id: type: string name: type: string created_at: type: string updated_at: type: string non_expiring: type: boolean required: - id - name - created_at - updated_at - non_expiring x-typelizer: true StoreCredit: type: object properties: id: type: string amount: type: string amount_used: type: string amount_remaining: type: string display_amount: type: string display_amount_used: type: string display_amount_remaining: type: string currency: type: string memo: type: string nullable: true metadata: type: object created_at: type: string updated_at: type: string customer_id: type: string nullable: true created_by_id: type: string nullable: true category_id: type: string nullable: true category_name: type: string nullable: true required: - id - amount - amount_used - amount_remaining - display_amount - display_amount_used - display_amount_remaining - currency - memo - metadata - created_at - updated_at - customer_id - created_by_id - category_id - category_name x-typelizer: true Store: type: object properties: id: type: string metadata: type: object name: type: string default_currency: type: string default_locale: type: string mail_from_address: type: string nullable: true customer_support_email: type: string nullable: true new_order_notifications_email: type: string nullable: true preferred_send_consumer_transactional_emails: type: boolean preferred_admin_locale: type: string nullable: true preferred_timezone: type: string preferred_weight_unit: type: string preferred_unit_system: type: string created_at: type: string updated_at: type: string url: type: string supported_currencies: type: array items: type: string supported_locales: type: array items: type: string logo_url: type: string nullable: true mailer_logo_url: type: string nullable: true required: - id - metadata - name - default_currency - default_locale - mail_from_address - customer_support_email - new_order_notifications_email - preferred_send_consumer_transactional_emails - preferred_admin_locale - preferred_timezone - preferred_weight_unit - preferred_unit_system - created_at - updated_at - url - supported_currencies - supported_locales - logo_url - mailer_logo_url x-typelizer: true TaxCategory: type: object properties: id: type: string name: type: string tax_code: type: string nullable: true description: type: string nullable: true is_default: type: boolean created_at: type: string updated_at: type: string required: - id - name - tax_code - description - is_default - created_at - updated_at x-typelizer: true Variant: type: object properties: id: type: string product_id: type: string sku: type: string nullable: true options_text: type: string track_inventory: type: boolean media_count: type: number thumbnail_url: type: string nullable: true purchasable: type: boolean in_stock: type: boolean backorderable: type: boolean weight: type: number nullable: true height: type: number nullable: true width: type: number nullable: true depth: type: number nullable: true price: "$ref": "#/components/schemas/Price" original_price: allOf: - "$ref": "#/components/schemas/Price" nullable: true primary_media: "$ref": "#/components/schemas/Media" media: type: array items: "$ref": "#/components/schemas/Media" option_values: type: array items: "$ref": "#/components/schemas/OptionValue" custom_fields: type: array items: "$ref": "#/components/schemas/CustomField" prior_price: allOf: - "$ref": "#/components/schemas/PriceHistory" nullable: true metadata: type: object position: type: number cost_price: type: string nullable: true cost_currency: type: string nullable: true barcode: type: string nullable: true weight_unit: type: string nullable: true dimensions_unit: type: string nullable: true deleted_at: type: string nullable: true created_at: type: string updated_at: type: string tax_category_id: type: string nullable: true available_stock: type: number nullable: true reserved_quantity: type: number total_on_hand: type: number nullable: true product_name: type: string prices: type: array items: "$ref": "#/components/schemas/Price" stock_items: type: array items: "$ref": "#/components/schemas/StockItem" required: - id - product_id - sku - options_text - track_inventory - media_count - thumbnail_url - purchasable - in_stock - backorderable - weight - height - width - depth - price - original_price - option_values - metadata - position - cost_price - cost_currency - barcode - weight_unit - dimensions_unit - deleted_at - created_at - updated_at - tax_category_id - available_stock - reserved_quantity - total_on_hand - product_name x-typelizer: true WebhookDelivery: type: object properties: id: type: string event_name: type: string event_id: type: string nullable: true response_code: type: number nullable: true execution_time: type: number nullable: true error_type: type: string nullable: true request_errors: type: string nullable: true response_body: type: string nullable: true success: type: boolean nullable: true payload: type: object created_at: type: string updated_at: type: string delivered_at: type: string nullable: true webhook_endpoint_id: type: string webhook_endpoint_url: type: string required: - id - event_name - event_id - response_code - execution_time - error_type - request_errors - response_body - success - payload - created_at - updated_at - delivered_at - webhook_endpoint_id - webhook_endpoint_url x-typelizer: true WebhookEndpoint: type: object properties: id: type: string name: type: string nullable: true url: type: string active: type: boolean subscriptions: type: array items: type: string disabled_reason: type: string nullable: true created_at: type: string updated_at: type: string disabled_at: type: string nullable: true secret_key: type: string nullable: true last_delivery_at: type: string nullable: true recent_delivery_count: type: number recent_failure_count: type: number total_delivery_count: type: number successful_delivery_count: type: number failed_delivery_count: type: number required: - id - name - url - active - subscriptions - disabled_reason - created_at - updated_at - disabled_at - secret_key - last_delivery_at - recent_delivery_count - recent_failure_count - total_delivery_count - successful_delivery_count - failed_delivery_count x-typelizer: true