openapi: 3.0.3 info: title: Admin Account / Address Pricing 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.\n\n## Authentication\n\nThe Admin API requires a secret API key passed in the `x-spree-api-key` header.\nSecret API keys can be generated in the Spree admin dashboard.\n\n## Response Format\n\nAll responses are JSON. List endpoints return paginated responses with `data` and `meta` keys.\nSingle resource endpoints return a flat JSON object.\n\n## Resource IDs\n\nEvery resource is identified by an opaque string ID (e.g. `prod_86Rf07xd4z`,\n`variant_k5nR8xLq`, `or_UkLWZg9DAJ`). Use these IDs everywhere — URL paths,\nrequest bodies, and Ransack filters all accept them directly.\n\n## Error Handling\n\nErrors return a consistent format:\n```json\n{\n \"error\": {\n \"code\": \"validation_error\",\n \"message\": \"Validation failed\",\n \"details\": { \"name\": [\"can't be blank\"] }\n }\n}\n```\n" version: v3 servers: - url: http://{defaultHost} variables: defaultHost: default: localhost:3000 tags: - name: Pricing description: Prices and price lists for currency-, market-, and customer-group-specific pricing paths: /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: null status: draft position: 1 match_policy: all starts_at: null ends_at: null deleted_at: null 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: null status: draft position: 2 match_policy: all starts_at: null ends_at: null deleted_at: null 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: null next: null 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: null status: draft position: 3 match_policy: all starts_at: null ends_at: null deleted_at: null 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: null status: draft position: 1 match_policy: all starts_at: null ends_at: null deleted_at: null 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: null status: draft position: 1 match_policy: all starts_at: null ends_at: null deleted_at: null 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: null status: active position: 1 match_policy: all starts_at: null ends_at: null deleted_at: null 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: null status: inactive position: 1 match_policy: all starts_at: null ends_at: null deleted_at: null 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'\n\nconst client = createAdminClient({\n baseUrl: 'https://your-store.com',\n secretKey: 'sk_xxx',\n})\n\nconst { data: prices } = await client.prices.list({\n price_list_id_eq: 'pl_xxx',\n currency_eq: 'USD',\n expand: ['variant'],\n})" 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: null compare_at_amount_in_cents: null currency: USD display_amount: $19.99 display_compare_at_amount: null price_list_id: null 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: null compare_at_amount_in_cents: null currency: USD display_amount: $5.00 display_compare_at_amount: null 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: null next: null 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'\n\nconst client = createAdminClient({\n baseUrl: 'https://your-store.com',\n secretKey: 'sk_xxx',\n})\n\nconst price = await client.prices.create({\n variant_id: 'variant_xxx',\n currency: 'USD',\n amount: '19.99',\n})" 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: null compare_at_amount_in_cents: null currency: EUR display_amount: €9.99 display_compare_at_amount: null price_list_id: null 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'\n\nconst client = createAdminClient({\n baseUrl: 'https://your-store.com',\n secretKey: 'sk_xxx',\n})\n\nconst 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: null compare_at_amount_in_cents: null currency: USD display_amount: $5.00 display_compare_at_amount: null 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'\n\nconst client = createAdminClient({\n baseUrl: 'https://your-store.com',\n secretKey: 'sk_xxx',\n})\n\nconst price = await client.prices.update('price_xxx', {\n amount: '12.34',\n})" 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: null compare_at_amount_in_cents: null currency: USD display_amount: $12.34 display_compare_at_amount: null 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'\n\nconst client = createAdminClient({\n baseUrl: 'https://your-store.com',\n secretKey: 'sk_xxx',\n})\n\nawait 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.\n\nEach row either:\n* targets an existing price by `id`, OR\n* matches on the unique key `(variant_id, currency, price_list_id)` —\n updating the existing row if one exists, creating one otherwise.\n\nModel callbacks (e.g. PriceHistory) are bypassed; this is a\nbulk-write fast path for the admin spreadsheet. The response\ncarries `price_count` — the number of rows touched.\n\n\n**Required scope:** `write_products` (for API-key authentication)." x-codeSamples: - lang: javascript label: Spree Admin SDK source: "import { createAdminClient } from '@spree/admin-sdk'\n\nconst client = createAdminClient({\n baseUrl: 'https://your-store.com',\n secretKey: 'sk_xxx',\n})\n\nconst { price_count } = await client.prices.bulkUpsert({\n prices: [\n {\n variant_id: 'variant_xxx',\n currency: 'USD',\n price_list_id: 'pl_xxx',\n amount: '11.11',\n },\n {\n variant_id: 'variant_yyy',\n currency: 'USD',\n price_list_id: 'pl_xxx',\n amount: '22.22',\n },\n ],\n})" 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'\n\nconst client = createAdminClient({\n baseUrl: 'https://your-store.com',\n secretKey: 'sk_xxx',\n})\n\nconst { price_count } = await client.prices.bulkDestroy({\n ids: ['price_xxx', 'price_yyy'],\n})" 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 components: schemas: 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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: null description: Previous page number next: type: integer nullable: true example: 2 description: Next page number required: - page - limit - count - pages - from - to - in 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 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 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 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 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