---
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.

        The `provider` field selects the authentication method. When omitted it
        defaults to `email`, the built-in email/password login.

        To authenticate against a third-party identity provider (Okta, Azure AD,
        Google Workspace SSO, a custom JWT issuer, SAML, etc.), send
        `{ "provider": "<your_key>", ... }` with the fields that provider
        requires. The endpoint returns the same JWT regardless of which provider
        authenticated the request. See
        [Custom API Authentication](https://spreecommerce.org/docs/developer/how-to/custom-api-authentication)
        for the list of configured providers and their required fields.
      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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /auth/login -d '{"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.eyJ1c2VyX2lkIjoxLCJ1c2VyX3R5cGUiOiJhZG1pbiIsImp0aSI6IjE3NmVlN2M3LWJkYzktNGM1MS1hMzFiLTEwMDYxOTc3NGZmNCIsImlzcyI6InNwcmVlIiwiYXVkIjoiYWRtaW5fYXBpIiwiZXhwIjoxNzY4NDc4NzAwfQ.t4Ntas5E8dwfI8wxMdwcC-XVFXWzaFSAFL8_Mv4HnlU
                user:
                  id: adm_UkLWZg9DAJ
                  email: admin@example.com
                  first_name: Gavin
                  last_name: Swift
                  full_name: Gavin Swift
                  selected_locale:
                  status: active
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  last_active_at:
                  avatar_url:
                  roles:
                  - id: role_UkLWZg9DAJ
                    name: admin
                  stores:
                  - id: store_UkLWZg9DAJ
                    name: Spree Test Store
                    code: spree_1
              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 configured
                  authentication provider; the remaining fields are forwarded to it.
                  Required fields depend on the provider — see
                  [Custom API Authentication](https://spreecommerce.org/docs/developer/how-to/custom-api-authentication).
                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()
      - lang: bash
        label: Spree CLI
        source: spree api post /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.eyJ1c2VyX2lkIjoxLCJ1c2VyX3R5cGUiOiJhZG1pbiIsImp0aSI6ImFiN2M4YjAxLTY0MGYtNDJhZi1hZTY1LTQxY2NmOTk1YmVlMCIsImlzcyI6InNwcmVlIiwiYXVkIjoiYWRtaW5fYXBpIiwiZXhwIjoxNzY4NDc4NzAwfQ.oXS2FwkI2rK4WOX4QUNW4oTPu7gzMmB9Y9oqsJpW7SY
                user:
                  id: adm_UkLWZg9DAJ
                  email: admin@example.com
                  first_name: Clarine
                  last_name: Jenkins
                  full_name: Clarine Jenkins
                  selected_locale:
                  status: active
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  last_active_at: '2026-01-15T12:00:00Z'
                  avatar_url:
                  roles:
                  - id: role_UkLWZg9DAJ
                    name: admin
                  stores:
                  - id: store_UkLWZg9DAJ
                    name: Spree Test Store
                    code: spree_1
              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()
      - lang: bash
        label: Spree CLI
        source: spree api post /auth/logout
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '204':
          description: logout successful
  "/api/v3/admin/auth/invitations/{id}/accept":
    parameters:
    - name: id
      in: path
      description: Invitation ID from the emailed link
      required: true
      schema:
        type: string
    post:
      summary: Accept an invitation
      tags:
      - Authentication
      description: |
        Accepts a staff invitation and returns a signed-in admin session, so the
        new member lands in the dashboard rather than on a login form.

        Unauthenticated — the ID and token in the emailed link are the
        credential. The email is never taken from the request; it always comes
        from the invitation.

        `password` is required when no account exists for the invited address,
        in which case it sets one. When an account already exists, the same
        field is how the person proves the account is theirs — unless the
        request carries that account's own access token, which proves it
        already.
      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 invitation ID and token come from the link in the invitation email.
          // An invitee without an account sets a password here; one with an account
          // signs in with theirs. The refresh token is set as an HttpOnly cookie.
          const auth = await client.auth.acceptInvitation('inv_UkLWZg9DAJ', 'xK3pQ9vLmT2wRz8N', {
            password: 'password123',
            password_confirmation: 'password123',
            first_name: 'Robin',
            last_name: 'Ellis',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /auth/invitations/{id}/accept -d '{"password":"password123","password_confirmation":"password123","first_name":"Robin","last_name":"Ellis"}'
      parameters:
      - name: token
        in: query
        required: true
        description: The token from the emailed link
        schema:
          type: string
      responses:
        '200':
          description: invitation accepted, session issued
          content:
            application/json:
              example:
                token: eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoyLCJ1c2VyX3R5cGUiOiJhZG1pbiIsImp0aSI6IjQ2MzZlMDBiLTdmZGMtNDk1Mi1hNzhhLTI4YmEyMTVjNDk0MSIsImlzcyI6InNwcmVlIiwiYXVkIjoiYWRtaW5fYXBpIiwiZXhwIjoxNzY4NDc4NzAwfQ.AwpPaRCvRIV36C8k4nChul5s7yq_yWFTSy_TyVlrbXA
                user:
                  id: adm_gbHJdmfrXB
                  email: newcomer@acme.test
                  first_name: Robin
                  last_name: Ellis
                  full_name: Robin Ellis
                  selected_locale:
                  status: active
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  last_active_at:
                  avatar_url:
                  roles:
                  - id: role_UkLWZg9DAJ
                    name: admin
                  stores:
                  - id: store_UkLWZg9DAJ
                    name: Spree Test Store
                    code: spree_1
              schema:
                "$ref": "#/components/schemas/AuthResponse"
        '404':
          description: wrong token, or an invitation that can no longer be accepted
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Invitation not found, expired, or already accepted
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/InvitationAcceptParams"
        required: true
  "/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('product'),
            )
          ) {
            // show "Create product" button
          }
      - lang: bash
        label: Spree CLI
        source: spree api get /me
      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: adm_UkLWZg9DAJ
                  email: annabelle@brekke.info
                  first_name: Zenobia
                  last_name: Sanford
                  full_name: Zenobia Sanford
                  selected_locale:
                  status: active
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  last_active_at:
                  avatar_url:
                  roles:
                  - id: role_UkLWZg9DAJ
                    name: admin
                  stores:
                  - id: store_UkLWZg9DAJ
                    name: Spree Test Store
                    code: spree_1
                permissions:
                - allow: true
                  actions:
                  - manage
                  subjects:
                  - all
                  has_conditions: false
                permission_keys:
                - read_dashboard
                - read_reports
                - write_reports
                - read_orders
                - write_orders
                - read_payments
                - write_payments
                - read_fulfillments
                - write_fulfillments
                - read_refunds
                - write_refunds
                - read_products
                - write_products
                - read_product_types
                - write_product_types
                - read_publishing
                - write_publishing
                - read_media
                - write_media
                - read_categories
                - write_categories
                - read_collections
                - write_collections
                - read_stock
                - write_stock
                - read_purchasing
                - write_purchasing
                - read_customers
                - write_customers
                - read_sellers
                - write_sellers
                - read_commissions
                - write_commissions
                - read_payouts
                - write_payouts
                - read_gift_cards
                - write_gift_cards
                - read_store_credits
                - write_store_credits
                - read_promotions
                - write_promotions
                - read_settings
                - write_settings
                - read_delivery_methods
                - write_delivery_methods
                - read_package_types
                - write_package_types
                - read_webhooks
                - write_webhooks
                - read_email_templates
                - write_email_templates
                - read_integrations
                - write_integrations
                - read_maintenance_tasks
                - write_maintenance_tasks
                - read_api_keys
                - write_api_keys
                - read_oauth_applications
                - write_oauth_applications
                - read_staff
                - write_staff
              schema:
                "$ref": "#/components/schemas/MeResponse"
        '401':
          description: unauthorized
          content:
            application/json:
              example:
                error:
                  code: authentication_required
                  message: Authentication required
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update the current admin profile
      tags:
      - Authentication
      security:
      - api_key: []
        bearer_auth: []
      description: Self-service update of the signed-in admin's own profile, such
        as their admin UI display language (`selected_locale`).
      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',
          })

          // Set the signed-in admin's own UI display language.
          const me = await client.me.update({
            selected_locale: 'de',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /me -d '{"selected_locale":"de"}'
      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: profile updated
          content:
            application/json:
              example:
                user:
                  id: adm_UkLWZg9DAJ
                  email: marlana.bergnaum@halvorsonbosco.co.uk
                  first_name: See
                  last_name: Kuhlman
                  full_name: See Kuhlman
                  selected_locale: de
                  status: active
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  last_active_at:
                  avatar_url:
                  roles:
                  - id: role_UkLWZg9DAJ
                    name: admin
                  stores:
                  - id: store_UkLWZg9DAJ
                    name: Spree Test Store
                    code: spree_1
                permissions:
                - allow: true
                  actions:
                  - manage
                  subjects:
                  - all
                  has_conditions: false
                permission_keys:
                - read_dashboard
                - read_reports
                - write_reports
                - read_orders
                - write_orders
                - read_payments
                - write_payments
                - read_fulfillments
                - write_fulfillments
                - read_refunds
                - write_refunds
                - read_products
                - write_products
                - read_product_types
                - write_product_types
                - read_publishing
                - write_publishing
                - read_media
                - write_media
                - read_categories
                - write_categories
                - read_collections
                - write_collections
                - read_stock
                - write_stock
                - read_purchasing
                - write_purchasing
                - read_customers
                - write_customers
                - read_sellers
                - write_sellers
                - read_commissions
                - write_commissions
                - read_payouts
                - write_payouts
                - read_gift_cards
                - write_gift_cards
                - read_store_credits
                - write_store_credits
                - read_promotions
                - write_promotions
                - read_settings
                - write_settings
                - read_delivery_methods
                - write_delivery_methods
                - read_package_types
                - write_package_types
                - read_webhooks
                - write_webhooks
                - read_email_templates
                - write_email_templates
                - read_integrations
                - write_integrations
                - read_maintenance_tasks
                - write_maintenance_tasks
                - read_api_keys
                - write_api_keys
                - read_oauth_applications
                - write_oauth_applications
                - read_staff
                - write_staff
              schema:
                "$ref": "#/components/schemas/MeResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/MeUpdateParams"
        required: true
  "/api/v3/admin/auth/password_resets":
    post:
      summary: Request password reset
      tags:
      - Authentication
      security:
      - api_key: []
      description: |
        Requests a password reset email for an admin user. Always returns `202`
        whether or not the email matches an account, to prevent enumeration.

        `redirect_url` is where the emailed link should point (the reset token
        is appended as a `token` query param). It is honoured only on the
        dashboard's origin and for an account that is staff of the store —
        otherwise it is silently ignored and the link opens the dashboard's
        reset page. The email is delivered by Spree itself via the
        `admin_user.password_reset_requested` event; this event is never
        forwarded to webhook endpoints.
      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',
          })

          // Always resolves (202) whether or not the email exists — no account enumeration.
          // The emailed link points at redirect_url with the reset token appended as ?token=.
          await client.auth.requestPasswordReset({
            email: 'admin@example.com',
            redirect_url: 'https://admin.your-store.com/reset-password',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /auth/password_resets -d '{"email":"admin@example.com","redirect_url":"https://admin.your-store.com/reset-password"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '202':
          description: reset requested
          content:
            application/json:
              example:
                message: If an account exists for that email, password reset instructions
                  have been sent.
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PasswordResetRequestParams"
        required: true
  "/api/v3/admin/auth/password_resets/{id}":
    patch:
      summary: Reset password
      tags:
      - Authentication
      security:
      - api_key: []
      description: |
        Consumes a password reset token (the `token` query param from the
        emailed link), sets the new password, and signs the admin in: the
        response carries a JWT access token and the rotatable refresh token is
        set in an HttpOnly cookie. The token is single-use — it invalidates as
        soon as the password changes.
      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 token comes from the emailed link's ?token= param. On success the admin
          // is signed in: a JWT comes back and the refresh token is set as an HttpOnly cookie.
          const auth = await client.auth.resetPassword('reset-token-from-email', {
            password: 'new-password-123',
            password_confirmation: 'new-password-123',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /auth/password_resets/{id} -d '{"password":"new-password-123","password_confirmation":"new-password-123"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: id
        in: path
        description: The reset token from the emailed link
        required: true
        schema:
          type: string
      responses:
        '200':
          description: password reset
          content:
            application/json:
              example:
                token: eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VyX3R5cGUiOiJhZG1pbiIsImp0aSI6IjBiZTdhM2RmLWEyYzYtNDZkOC1hNTZiLWE4NDg4MGIyZGZiNCIsImlzcyI6InNwcmVlIiwiYXVkIjoiYWRtaW5fYXBpIiwiZXhwIjoxNzY4NDgyMDAwfQ.Vo2RzprqsH2XBa8DaSQ6awyXqlBA5QDFA5R7ygTezXY
                user:
                  id: adm_UkLWZg9DAJ
                  email: admin@example.com
                  first_name: Olga
                  last_name: Schneider
                  full_name: Olga Schneider
                  selected_locale:
                  status: active
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  last_active_at:
                  avatar_url:
                  roles:
                  - id: role_UkLWZg9DAJ
                    name: admin
                  stores:
                  - id: store_UkLWZg9DAJ
                    name: Spree Test Store
                    code: spree_1
              schema:
                "$ref": "#/components/schemas/AuthResponse"
        '422':
          description: invalid or expired token
          content:
            application/json:
              example:
                error:
                  code: password_reset_token_invalid
                  message: Password reset token is invalid or has expired.
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PasswordResetParams"
        required: true
  "/api/v3/admin/auth/setup":
    get:
      summary: Check first-run setup availability
      tags:
      - Authentication
      description: |
        Reports whether first-run setup is still available — true only while
        the installation has no admin user. Unauthenticated; the dashboard
        login page uses it to offer the setup screen.
      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',
          })

          // True only until the installation has its first admin user.
          const { setup_required } = await client.auth.setupStatus()
      - lang: bash
        label: Spree CLI
        source: spree api get /auth/setup
      responses:
        '200':
          description: setup status
          content:
            application/json:
              example:
                setup_required: true
    post:
      summary: Complete first-run setup
      tags:
      - Authentication
      description: |
        Creates the first admin account and adopts the seeded store, authorized
        by the one-time setup token printed at install time (rotate it with
        `bin/rails spree:setup:token`). Issues a JWT access token and a
        refresh-token cookie exactly like login. Returns 404 once any admin
        user exists — the flow is closed permanently after setup.
      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 setup token is printed when Spree is installed. The refresh token is
          // set as an HttpOnly cookie; only `token` and `user` come back in the body.
          const auth = await client.auth.completeSetup({
            setup_token: 'st_9f2c4e7a1b8d',
            email: 'owner@example.com',
            password: 'Secret123!',
            password_confirmation: 'Secret123!',
            first_name: 'Olivia',
            last_name: 'Owner',
            store_name: 'My Store',
            country_code: 'US',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /auth/setup -d '{"setup_token":"st_9f2c4e7a1b8d","email":"owner@example.com","password":"Secret123!","password_confirmation":"Secret123!","first_name":"Olivia","last_name":"Owner","store_name":"My
          Store","country_code":"US"}'
      parameters: []
      responses:
        '200':
          description: setup completed
          content:
            application/json:
              example:
                token: eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VyX3R5cGUiOiJhZG1pbiIsImp0aSI6IjZjMjg1ODk5LTExMzUtNDBhMi1hNDBiLTE4NjNiODcwZDRjYyIsImlzcyI6InNwcmVlIiwiYXVkIjoiYWRtaW5fYXBpIiwiZXhwIjoxNzY4NDc4NzAwfQ.Go2eUEiXf7rVD5mwtNMqkWqUGcBfhxk3b7JT8dw8uiE
                user:
                  id: adm_UkLWZg9DAJ
                  email: owner@example.com
                  first_name: Olivia
                  last_name: Owner
                  full_name: Olivia Owner
                  selected_locale:
                  status: active
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  last_active_at:
                  avatar_url:
                  roles:
                  - id: role_UkLWZg9DAJ
                    name: admin
                  stores:
                  - id: store_UkLWZg9DAJ
                    name: My Store
                    code: spree_1
        '404':
          description: setup not available
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Setup is not available
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SetupParams"
        required: true
  "/api/v3/admin/auth/setup/countries":
    get:
      summary: List countries for first-run setup
      tags:
      - Authentication
      description: |
        Countries the store can be set up in, each with the currency and
        official languages derived from it. Unauthenticated, because the setup
        screen runs before any credential exists. Returns 404 once any admin
        user exists.
      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',
          })

          // Each country comes with the currency and languages the store would start with.
          const { countries } = await client.auth.setupCountries()
      - lang: bash
        label: Spree CLI
        source: spree api get /auth/setup/countries
      responses:
        '200':
          description: countries
          content:
            application/json:
              example:
                countries:
                - code: AD
                  currency: EUR
                  locales:
                  - ca
                - code: AE
                  currency: AED
                  locales:
                  - ar
                - code: AF
                  currency: AFN
                  locales:
                  - ps
                  - uz
                  - tk
                - code: AG
                  currency: XCD
                  locales:
                  - en
                - code: AI
                  currency: XCD
                  locales:
                  - en
                - code: AL
                  currency: ALL
                  locales:
                  - sq
                - code: AM
                  currency: AMD
                  locales:
                  - hy
                - code: AO
                  currency: AOA
                  locales:
                  - pt
                - code: AR
                  currency: ARS
                  locales:
                  - es
                  - gn
                - code: AS
                  currency: USD
                  locales:
                  - en
                  - sm
                - code: AT
                  currency: EUR
                  locales:
                  - de
                - code: AU
                  currency: AUD
                  locales:
                  - en
                - code: AW
                  currency: AWG
                  locales:
                  - nl
                - code: AZ
                  currency: AZN
                  locales:
                  - az
                  - hy
                - code: BA
                  currency: BAM
                  locales:
                  - bs
                  - hr
                  - sr
                - code: BB
                  currency: BBD
                  locales:
                  - en
                - code: BD
                  currency: BDT
                  locales:
                  - bn
                - code: BE
                  currency: EUR
                  locales:
                  - nl
                  - fr
                  - de
                - code: BF
                  currency: XOF
                  locales:
                  - fr
                  - ff
                - code: BG
                  currency: EUR
                  locales:
                  - bg
                - code: BH
                  currency: BHD
                  locales:
                  - ar
                - code: BI
                  currency: BIF
                  locales:
                  - fr
                  - rn
                - code: BJ
                  currency: XOF
                  locales:
                  - fr
                - code: BL
                  currency: EUR
                  locales:
                  - fr
                - code: BM
                  currency: BMD
                  locales:
                  - en
                - code: BN
                  currency: BND
                  locales:
                  - ms
                - code: BO
                  currency: BOB
                  locales:
                  - es
                  - ay
                  - qu
                - code: BQ
                  currency: USD
                  locales:
                  - nl
                  - en
                - code: BR
                  currency: BRL
                  locales:
                  - pt
                - code: BS
                  currency: BSD
                  locales:
                  - en
                - code: BT
                  currency: BTN
                  locales:
                  - dz
                - code: BW
                  currency: BWP
                  locales:
                  - en
                  - tn
                - code: BY
                  currency: BYN
                  locales:
                  - be
                  - ru
                - code: BZ
                  currency: BZD
                  locales:
                  - en
                  - es
                - code: CA
                  currency: CAD
                  locales:
                  - en
                  - fr
                - code: CC
                  currency: AUD
                  locales:
                  - en
                - code: CD
                  currency: CDF
                  locales:
                  - fr
                  - ln
                  - kg
                  - sw
                  - lu
                - code: CF
                  currency: XAF
                  locales:
                  - fr
                  - sg
                - code: CG
                  currency: XAF
                  locales:
                  - fr
                  - ln
                - code: CH
                  currency: CHF
                  locales:
                  - de
                  - fr
                  - it
                  - rm
                - code: CI
                  currency: XOF
                  locales:
                  - fr
                - code: CK
                  currency: NZD
                  locales:
                  - en
                - code: CL
                  currency: CLP
                  locales:
                  - es
                - code: CM
                  currency: XAF
                  locales:
                  - en
                  - fr
                - code: CN
                  currency: CNY
                  locales:
                  - zh-CN
                - code: CO
                  currency: COP
                  locales:
                  - es
                - code: CR
                  currency: CRC
                  locales:
                  - es
                - code: CU
                  currency: CUP
                  locales:
                  - es
                - code: CV
                  currency: CVE
                  locales:
                  - pt
                - code: CW
                  currency: XCG
                  locales:
                  - nl
                - code: CX
                  currency: AUD
                  locales:
                  - en
                  - zh-CN
                  - ms
                - code: CY
                  currency: EUR
                  locales:
                  - el
                  - tr
                  - hy
                - code: CZ
                  currency: CZK
                  locales:
                  - cs
                - code: DE
                  currency: EUR
                  locales:
                  - de
                - code: DJ
                  currency: DJF
                  locales:
                  - ar
                  - fr
                - code: DK
                  currency: DKK
                  locales:
                  - da
                - code: DM
                  currency: XCD
                  locales:
                  - en
                - code: DO
                  currency: DOP
                  locales:
                  - es
                - code: DZ
                  currency: DZD
                  locales:
                  - ar
                - code: EC
                  currency: USD
                  locales:
                  - es
                - code: EE
                  currency: EUR
                  locales:
                  - et
                - code: EG
                  currency: EGP
                  locales:
                  - ar
                - code: ER
                  currency: ERN
                  locales:
                  - en
                  - ar
                  - ti
                - code: ES
                  currency: EUR
                  locales:
                  - es
                - code: ET
                  currency: ETB
                  locales:
                  - am
                - code: FI
                  currency: EUR
                  locales:
                  - fi
                  - sv
                - code: FJ
                  currency: FJD
                  locales:
                  - en
                  - fj
                  - hi
                - code: FK
                  currency: FKP
                  locales:
                  - en
                - code: FM
                  currency: USD
                  locales:
                  - en
                - code: FO
                  currency: DKK
                  locales:
                  - fo
                - code: FR
                  currency: EUR
                  locales:
                  - fr
                - code: GA
                  currency: XAF
                  locales:
                  - fr
                - code: GB
                  currency: GBP
                  locales:
                  - en
                - code: GD
                  currency: XCD
                  locales:
                  - en
                - code: GE
                  currency: GEL
                  locales:
                  - ka
                - code: GF
                  currency: EUR
                  locales:
                  - fr
                - code: GG
                  currency: GBP
                  locales:
                  - en
                  - fr
                - code: GH
                  currency: GHS
                  locales:
                  - en
                - code: GI
                  currency: GIP
                  locales:
                  - en
                - code: GL
                  currency: DKK
                  locales:
                  - kl
                - code: GM
                  currency: GMD
                  locales:
                  - en
                - code: GN
                  currency: GNF
                  locales:
                  - fr
                  - ff
                - code: GP
                  currency: EUR
                  locales:
                  - fr
                - code: GQ
                  currency: XAF
                  locales:
                  - es
                  - fr
                - code: GR
                  currency: EUR
                  locales:
                  - el
                - code: GT
                  currency: GTQ
                  locales:
                  - es
                - code: GU
                  currency: USD
                  locales:
                  - en
                  - ch
                  - es
                - code: GW
                  currency: XOF
                  locales:
                  - pt
                - code: GY
                  currency: GYD
                  locales:
                  - en
                - code: HK
                  currency: HKD
                  locales:
                  - en
                  - zh-CN
                - code: HN
                  currency: HNL
                  locales:
                  - es
                - code: HR
                  currency: EUR
                  locales:
                  - hr
                - code: HT
                  currency: HTG
                  locales:
                  - fr
                  - ht
                - code: HU
                  currency: HUF
                  locales:
                  - hu
                - code: ID
                  currency: IDR
                  locales:
                  - id
                - code: IE
                  currency: EUR
                  locales:
                  - en
                  - ga
                - code: IL
                  currency: ILS
                  locales:
                  - he
                  - ar
                - code: IM
                  currency: GBP
                  locales:
                  - en
                  - gv
                - code: IN
                  currency: INR
                  locales:
                  - hi
                  - en
                - code: IQ
                  currency: IQD
                  locales:
                  - ar
                - code: IR
                  currency: IRR
                  locales:
                  - fa
                - code: IS
                  currency: ISK
                  locales:
                  - is
                - code: IT
                  currency: EUR
                  locales:
                  - it
                - code: JE
                  currency: GBP
                  locales:
                  - en
                  - fr
                - code: JM
                  currency: JMD
                  locales:
                  - en
                - code: JO
                  currency: JOD
                  locales:
                  - ar
                - code: JP
                  currency: JPY
                  locales:
                  - ja
                - code: KE
                  currency: KES
                  locales:
                  - en
                  - sw
                - code: KG
                  currency: KGS
                  locales:
                  - ky
                  - ru
                - code: KH
                  currency: KHR
                  locales:
                  - km
                - code: KI
                  currency: AUD
                  locales:
                  - en
                - code: KM
                  currency: KMF
                  locales:
                  - ar
                  - fr
                - code: KN
                  currency: XCD
                  locales:
                  - en
                - code: KP
                  currency: KPW
                  locales:
                  - ko
                - code: KR
                  currency: KRW
                  locales:
                  - ko
                - code: KW
                  currency: KWD
                  locales:
                  - ar
                - code: KY
                  currency: KYD
                  locales:
                  - en
                - code: KZ
                  currency: KZT
                  locales:
                  - kk
                  - ru
                - code: LA
                  currency: LAK
                  locales:
                  - lo
                - code: LB
                  currency: LBP
                  locales:
                  - ar
                  - fr
                - code: LC
                  currency: XCD
                  locales:
                  - en
                - code: LI
                  currency: CHF
                  locales:
                  - de
                - code: LK
                  currency: LKR
                  locales:
                  - si
                  - ta
                - code: LR
                  currency: LRD
                  locales:
                  - en
                - code: LS
                  currency: LSL
                  locales:
                  - en
                  - st
                - code: LT
                  currency: EUR
                  locales:
                  - lt
                - code: LU
                  currency: EUR
                  locales:
                  - fr
                  - de
                  - lb
                - code: LV
                  currency: EUR
                  locales:
                  - lv
                - code: LY
                  currency: LYD
                  locales:
                  - ar
                - code: MA
                  currency: MAD
                  locales:
                  - ar
                - code: MC
                  currency: EUR
                  locales:
                  - fr
                - code: MD
                  currency: MDL
                  locales:
                  - ro
                - code: ME
                  currency: EUR
                  locales:
                  - sr
                  - bs
                  - sq
                  - hr
                - code: MF
                  currency: EUR
                  locales:
                  - en
                  - fr
                  - nl
                - code: MG
                  currency: MGA
                  locales:
                  - fr
                  - mg
                - code: MH
                  currency: USD
                  locales:
                  - en
                  - mh
                - code: MK
                  currency: MKD
                  locales:
                  - mk
                - code: ML
                  currency: XOF
                  locales:
                  - fr
                - code: MM
                  currency: MMK
                  locales:
                  - my
                - code: MN
                  currency: MNT
                  locales:
                  - mn
                - code: MO
                  currency: MOP
                  locales:
                  - zh-CN
                  - pt
                - code: MP
                  currency: USD
                  locales:
                  - en
                  - ch
                - code: MQ
                  currency: EUR
                  locales:
                  - fr
                - code: MR
                  currency: MRU
                  locales:
                  - ar
                  - fr
                - code: MS
                  currency: XCD
                  locales:
                  - en
                - code: MT
                  currency: EUR
                  locales:
                  - mt
                  - en
                - code: MU
                  currency: MUR
                  locales:
                  - en
                - code: MV
                  currency: MVR
                  locales:
                  - dv
                - code: MW
                  currency: MWK
                  locales:
                  - en
                  - ny
                - code: MX
                  currency: MXN
                  locales:
                  - es
                - code: MY
                  currency: MYR
                  locales:
                  - ms
                  - en
                - code: MZ
                  currency: MZN
                  locales:
                  - pt
                - code: NA
                  currency: NAD
                  locales:
                  - en
                  - af
                - code: NC
                  currency: XPF
                  locales:
                  - fr
                - code: NE
                  currency: XOF
                  locales:
                  - fr
                - code: NF
                  currency: AUD
                  locales:
                  - en
                - code: NG
                  currency: NGN
                  locales:
                  - en
                - code: NI
                  currency: NIO
                  locales:
                  - es
                - code: NL
                  currency: EUR
                  locales:
                  - nl
                - code: 'NO'
                  currency: NOK
                  locales:
                  - nb
                  - nn
                - code: NP
                  currency: NPR
                  locales:
                  - ne
                - code: NR
                  currency: AUD
                  locales:
                  - en
                  - na
                - code: NU
                  currency: NZD
                  locales:
                  - en
                - code: NZ
                  currency: NZD
                  locales:
                  - en
                - code: OM
                  currency: OMR
                  locales:
                  - ar
                - code: PA
                  currency: PAB
                  locales:
                  - es
                - code: PE
                  currency: PEN
                  locales:
                  - es
                - code: PF
                  currency: XPF
                  locales:
                  - fr
                - code: PG
                  currency: PGK
                  locales:
                  - en
                - code: PH
                  currency: PHP
                  locales:
                  - tl
                  - en
                - code: PK
                  currency: PKR
                  locales:
                  - en
                  - ur
                - code: PL
                  currency: PLN
                  locales:
                  - pl
                - code: PM
                  currency: EUR
                  locales:
                  - fr
                - code: PN
                  currency: NZD
                  locales:
                  - en
                - code: PR
                  currency: USD
                  locales:
                  - es
                  - en
                - code: PS
                  currency: ILS
                  locales:
                  - ar
                  - he
                  - en
                - code: PT
                  currency: EUR
                  locales:
                  - pt
                - code: PW
                  currency: USD
                  locales:
                  - en
                - code: PY
                  currency: PYG
                  locales:
                  - es
                  - gn
                - code: QA
                  currency: QAR
                  locales:
                  - ar
                - code: RE
                  currency: EUR
                  locales:
                  - fr
                - code: RO
                  currency: RON
                  locales:
                  - ro
                - code: RS
                  currency: RSD
                  locales:
                  - sr
                - code: RU
                  currency: RUB
                  locales:
                  - ru
                - code: RW
                  currency: RWF
                  locales:
                  - rw
                  - en
                  - fr
                - code: SA
                  currency: SAR
                  locales:
                  - ar
                - code: SB
                  currency: SBD
                  locales:
                  - en
                - code: SC
                  currency: SCR
                  locales:
                  - fr
                  - en
                - code: SD
                  currency: SDG
                  locales:
                  - ar
                  - en
                - code: SE
                  currency: SEK
                  locales:
                  - sv
                - code: SG
                  currency: SGD
                  locales:
                  - en
                  - ms
                  - ta
                - code: SH
                  currency: SHP
                  locales:
                  - en
                - code: SI
                  currency: EUR
                  locales:
                  - sl
                - code: SJ
                  currency: NOK
                  locales:
                  - 'no'
                - code: SK
                  currency: EUR
                  locales:
                  - sk
                - code: SL
                  currency: SLE
                  locales:
                  - en
                - code: SM
                  currency: EUR
                  locales:
                  - it
                - code: SN
                  currency: XOF
                  locales:
                  - fr
                - code: SO
                  currency: SOS
                  locales:
                  - so
                  - ar
                - code: SR
                  currency: SRD
                  locales:
                  - nl
                - code: SS
                  currency: SSP
                  locales:
                  - ar
                  - en
                - code: ST
                  currency: STN
                  locales:
                  - pt
                - code: SV
                  currency: USD
                  locales:
                  - es
                - code: SX
                  currency: XCG
                  locales:
                  - nl
                  - en
                - code: SY
                  currency: SYP
                  locales:
                  - ar
                - code: SZ
                  currency: SZL
                  locales:
                  - en
                  - ss
                - code: TC
                  currency: USD
                  locales:
                  - en
                - code: TD
                  currency: XAF
                  locales:
                  - ar
                  - fr
                - code: TG
                  currency: XOF
                  locales:
                  - fr
                - code: TH
                  currency: THB
                  locales:
                  - th
                - code: TJ
                  currency: TJS
                  locales:
                  - tg
                  - ru
                - code: TK
                  currency: NZD
                  locales:
                  - en
                - code: TL
                  currency: IDR
                  locales:
                  - pt
                - code: TM
                  currency: TMT
                  locales:
                  - tk
                - code: TN
                  currency: TND
                  locales:
                  - ar
                  - fr
                - code: TO
                  currency: TOP
                  locales:
                  - en
                  - to
                - code: TR
                  currency: TRY
                  locales:
                  - tr
                - code: TT
                  currency: TTD
                  locales:
                  - en
                - code: TV
                  currency: AUD
                  locales:
                  - en
                - code: TW
                  currency: TWD
                  locales:
                  - zh-CN
                - code: TZ
                  currency: TZS
                  locales:
                  - sw
                  - en
                - code: UA
                  currency: UAH
                  locales:
                  - uk
                - code: UG
                  currency: UGX
                  locales:
                  - en
                  - sw
                - code: US
                  currency: USD
                  locales:
                  - en
                - code: UY
                  currency: UYU
                  locales:
                  - es
                - code: UZ
                  currency: UZS
                  locales:
                  - uz
                - code: VA
                  currency: EUR
                  locales:
                  - it
                  - la
                - code: VC
                  currency: XCD
                  locales:
                  - en
                - code: VE
                  currency: VES
                  locales:
                  - es
                - code: VG
                  currency: USD
                  locales:
                  - en
                - code: VI
                  currency: USD
                  locales:
                  - en
                - code: VN
                  currency: VND
                  locales:
                  - vi
                - code: VU
                  currency: VUV
                  locales:
                  - bi
                  - en
                  - fr
                - code: WF
                  currency: XPF
                  locales:
                  - fr
                - code: WS
                  currency: WST
                  locales:
                  - sm
                  - en
                - code: YE
                  currency: YER
                  locales:
                  - ar
                - code: YT
                  currency: EUR
                  locales:
                  - fr
                - code: ZA
                  currency: ZAR
                  locales:
                  - af
                  - en
                  - nr
                  - st
                  - ss
                  - tn
                  - ts
                  - ve
                  - xh
                  - zu
                - code: ZM
                  currency: ZMW
                  locales:
                  - en
                - code: ZW
                  currency: USD
                  locales:
                  - en
                  - sn
                  - nd
  "/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_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: origins } = await client.allowedOrigins.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /allowed_origins
      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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of origin (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - 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
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[origin_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `origin` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `origin`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: AllowedOrigin
        sortable:
        - created_at
        - id
        - origin
        - updated_at
      responses:
        '200':
          description: allowed origins found
          content:
            application/json:
              example:
                data:
                - id: ao_UkLWZg9DAJ
                  origin: https://shop.example.com
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                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_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 origin = await client.allowedOrigins.create({
            origin: 'https://admin.example.com',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /allowed_origins -d '{"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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/AllowedOrigin"
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Origin is invalid
                  details:
                    origin:
                    - code: invalid
                      message: is invalid
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/AllowedOriginCreateParams"
        required: true
  "/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_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 origin = await client.allowedOrigins.get('ao_xxx')
      - lang: bash
        label: Spree CLI
        source: spree api get /allowed_origins/{id}
      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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              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_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 origin = await client.allowedOrigins.update('ao_xxx', {
            origin: 'https://www.example.com',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /allowed_origins/{id} -d '{"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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              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:
                    - code: must_be_origin_only
                      message: must be an origin (scheme and host) without path, query,
                        or fragment
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/AllowedOriginUpdateParams"
        required: true
    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_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.allowedOrigins.delete('ao_xxx')
      - lang: bash
        label: Spree CLI
        source: spree api delete /allowed_origins/{id}
      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()
      - lang: bash
        label: Spree CLI
        source: spree api get /api_keys
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `name`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: ApiKey
        sortable:
        - created_at
        - id
        - name
        - updated_at
      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-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  revoked_at:
                  last_used_at:
                  channel_id:
                  plaintext_token: pk_K6zNkaVogFy735ukK6E7Qs1F
                  created_by_email:
                  created_by_type:
                  created_by_label:
                - id: key_gbHJdmfrXB
                  name: Backend integration
                  key_type: secret
                  token_prefix: sk_JiXS5S1gJ
                  scopes:
                  - write_all
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  revoked_at:
                  last_used_at:
                  channel_id:
                  plaintext_token:
                  created_by_email:
                  created_by_type:
                  created_by_label:
                - id: key_EfhxLZ9ck8
                  name: API key 14
                  key_type: secret
                  token_prefix: sk_vihKVmP6r
                  scopes:
                  - write_all
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  revoked_at:
                  last_used_at:
                  channel_id:
                  plaintext_token:
                  created_by_email:
                  created_by_type:
                  created_by_label:
                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.
      - lang: bash
        label: Spree CLI
        source: spree api post /api_keys -d '{"name":"Backend integration","key_type":"secret","scopes":["read_orders","write_orders"]}'
      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_kCkDUvba1
                scopes:
                - read_orders
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                revoked_at:
                last_used_at:
                channel_id:
                plaintext_token: sk_kCkDUvba1Z9gf8HAy29ih1Bj
                created_by_email: estella@okon.us
                created_by_type: admin_user
                created_by_label: Mana Cremin
        '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:
                    - code: blank
                      message: can't be blank
                      specific: false
                    scopes:
                    - code: blank
                      message: can't be blank
                      specific: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ApiKeyCreateParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /api_keys/{id}
      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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                revoked_at:
                last_used_at:
                channel_id:
                plaintext_token: pk_XyZ9qSxtdtD6Uewb3GXYKkoV
                created_by_email:
                created_by_type:
                created_by_label:
    patch:
      summary: Update an API key
      tags:
      - API Keys
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Renames a key. `key_type` and `scopes` are fixed at creation — to change a key's authority, create a new key and revoke the old one.

        **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',
          })

          // Only `name` is editable — scopes and key_type are fixed at creation.
          const key = await client.apiKeys.update('key_xxx', { name: 'CI key (renamed)' })
      - lang: bash
        label: Spree CLI
        source: spree api patch /api_keys/{id} -d '{"name":"CI key (renamed)"}'
      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 renamed
          content:
            application/json:
              example:
                id: key_gbHJdmfrXB
                name: Backend integration (renamed)
                key_type: secret
                token_prefix: sk_ZPBGFa2TH
                scopes:
                - write_all
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                revoked_at:
                last_used_at:
                channel_id:
                plaintext_token:
                created_by_email:
                created_by_type:
                created_by_label:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ApiKeyUpdateParams"
        required: true
    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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /api_keys/{id}
      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/current":
    get:
      summary: Describe the current API key
      tags:
      - API Keys
      security:
      - api_key: []
      description: |-
        Returns the secret key that authenticated this request, including its live scopes. Useful to confirm a key's real, current authority. Only secret-key principals have a single key to describe.

        **Required scope:** none — any key can describe itself (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',
          })

          // Describes the key you authenticated with, including its live scopes.
          const key = await client.apiKeys.current()
      - lang: bash
        label: Spree CLI
        source: spree api get /api_keys/current
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      responses:
        '200':
          description: current API key
          content:
            application/json:
              example:
                id: key_EfhxLZ9ck8
                name: API key 20
                key_type: secret
                token_prefix: sk_L5LVfygvH
                scopes:
                - write_all
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                revoked_at:
                last_used_at:
                channel_id:
                plaintext_token:
                created_by_email:
                created_by_type:
                created_by_label:
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api patch /api_keys/{id}/revoke -d '{ ... }'
      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_11yGX4rad
                scopes:
                - write_all
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                revoked_at: '2026-01-15T12:00:00.000Z'
                last_used_at:
                channel_id:
                plaintext_token:
                created_by_email:
                created_by_type:
                created_by_label:
  "/api/v3/admin/categories":
    get:
      summary: List categories
      tags:
      - Categories
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a paginated list of the store's categories (manual hierarchical taxons; rule-based collections are excluded).

        **Required scope:** `read_categories` (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.categories.list({
            name_cont: 'Shirts',
            limit: 25,
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /categories -d '{"name_cont":"Shirts","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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name and pretty name (partial, case-insensitive).
      - 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., children, parent,
          ancestors).
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `automatic` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `children_count` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `depth` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `parent_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `permalink` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `pretty_name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `products_count` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[parent_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `parent_` | `automatic`, `children_count`, `created_at`, `depth`, `id`, `name`, `parent_id`, `permalink`, `position`, `pretty_name`, `products_count`, `updated_at` |

          </Accordion>

          **Sort by:** `automatic`, `children_count`, `created_at`, `depth`, `id`, `name`, `parent_id`, `permalink`, `position`, `pretty_name`, `products_count`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Category
        sortable:
        - automatic
        - children_count
        - created_at
        - depth
        - id
        - name
        - parent_id
        - permalink
        - position
        - pretty_name
        - products_count
        - updated_at
      responses:
        '200':
          description: categories found
          content:
            application/json:
              example:
                data:
                - id: ctg_UkLWZg9DAJ
                  name: Clothing
                  permalink: clothing
                  position: 0
                  depth: 0
                  meta_title:
                  meta_description:
                  meta_keywords:
                  children_count: 0
                  parent_id:
                  description: ''
                  description_html: ''
                  image_url:
                  square_image_url:
                  is_root: true
                  is_child: false
                  is_leaf: true
                  external_references: {}
                  metadata: {}
                  pretty_name: Clothing
                  lft: 1
                  rgt: 2
                  products_count: 0
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                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/Category"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Create a category
      tags:
      - Categories
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Creates a category. Nests under the parent when parent_id is given, otherwise creates a top-level category.

        **Required scope:** `write_categories` (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.categories.create({
            name: 'Shirts',
            parent_id: 'ctg_UkLWZg9DAJ',
            description: '<p>Casual and dress shirts.</p>',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /categories -d '{"name":"Shirts","parent_id":"ctg_UkLWZg9DAJ","description":"<p>Casual
          and dress shirts.</p>"}'
      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: category created
          content:
            application/json:
              example:
                id: ctg_gbHJdmfrXB
                name: Shirts
                permalink: clothing/shirts
                position: 0
                depth: 1
                meta_title:
                meta_description:
                meta_keywords:
                children_count: 0
                parent_id: ctg_UkLWZg9DAJ
                description: ''
                description_html: ''
                image_url:
                square_image_url:
                is_root: false
                is_child: true
                is_leaf: true
                external_references: {}
                metadata: {}
                pretty_name: Clothing -> Shirts
                lft: 2
                rgt: 3
                products_count: 0
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/Category"
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CategoryCreateParams"
        required: true
  "/api/v3/admin/categories/{id}":
    get:
      summary: Get a category
      tags:
      - Categories
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a single category by ID.

        **Required scope:** `read_categories` (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.categories.get('ctg_UkLWZg9DAJ', {
            expand: ['children', 'ancestors'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /categories/{id} -d '{"expand":["children","ancestors"]}'
      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: Category ID
        schema:
          type: string
      - name: expand
        in: query
        required: false
        description: Comma-separated associations to expand (e.g., children, parent,
          ancestors).
        schema:
          type: string
      responses:
        '200':
          description: category found
          content:
            application/json:
              example:
                id: ctg_UkLWZg9DAJ
                name: Clothing
                permalink: clothing
                position: 0
                depth: 0
                meta_title:
                meta_description:
                meta_keywords:
                children_count: 0
                parent_id:
                description: ''
                description_html: ''
                image_url:
                square_image_url:
                is_root: true
                is_child: false
                is_leaf: true
                external_references: {}
                metadata: {}
                pretty_name: Clothing
                lft: 1
                rgt: 2
                products_count: 0
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/Category"
        '404':
          description: category not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Category not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update a category
      tags:
      - Categories
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Updates a category.

        **Required scope:** `write_categories` (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.categories.update('ctg_UkLWZg9DAJ', {
            name: 'Apparel',
            meta_title: 'Apparel for every season',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /categories/{id} -d '{"name":"Apparel","meta_title":"Apparel
          for every season"}'
      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: Category ID
        schema:
          type: string
      responses:
        '200':
          description: category updated
          content:
            application/json:
              example:
                id: ctg_UkLWZg9DAJ
                name: Apparel
                permalink: clothing
                position: 0
                depth: 0
                meta_title:
                meta_description:
                meta_keywords:
                children_count: 0
                parent_id:
                description: ''
                description_html: ''
                image_url:
                square_image_url:
                is_root: true
                is_child: false
                is_leaf: true
                external_references: {}
                metadata: {}
                pretty_name: Apparel
                lft: 1
                rgt: 2
                products_count: 0
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/Category"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CategoryUpdateParams"
        required: true
    delete:
      summary: Delete a category
      tags:
      - Categories
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Deletes a category and its descendants.

        **Required scope:** `write_categories` (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.categories.delete('ctg_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /categories/{id}
      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: Category ID
        schema:
          type: string
      responses:
        '204':
          description: category deleted
  "/api/v3/admin/categories/{id}/reposition":
    patch:
      summary: Reposition a category
      tags:
      - Categories
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Moves a category to a new parent and/or index within the tree.

        **Required scope:** `write_categories` (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',
          })

          // Moves the category under a new parent, as its first child.
          const category = await client.categories.reposition('ctg_gbHJdmfrXB', {
            new_parent_id: 'ctg_UkLWZg9DAJ',
            new_position: 0,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /categories/{id}/reposition -d '{"new_parent_id":"ctg_UkLWZg9DAJ","new_position":0}'
      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: Category ID
        schema:
          type: string
      responses:
        '200':
          description: category repositioned
          content:
            application/json:
              example:
                id: ctg_gbHJdmfrXB
                name: Footwear
                permalink: clothing/footwear
                position: 0
                depth: 1
                meta_title:
                meta_description:
                meta_keywords:
                children_count: 0
                parent_id: ctg_UkLWZg9DAJ
                description: ''
                description_html: ''
                image_url:
                square_image_url:
                is_root: false
                is_child: true
                is_leaf: true
                external_references: {}
                metadata: {}
                pretty_name: Clothing -> Footwear
                lft: 2
                rgt: 3
                products_count: 0
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/Category"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CategoryRepositionParams"
        required: true
  "/api/v3/admin/categories/{category_id}/products":
    get:
      summary: List category products
      tags:
      - Categories
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Products classified under the category, ordered by their classification position.

        **Required scope:** `read_categories` (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.categories.products.list('ctg_UkLWZg9DAJ', {
            limit: 25,
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /categories/{category_id}/products -d '{"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: category_id
        in: path
        required: true
        description: Category ID
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches product name or variant SKU (partial, case-insensitive),
          and the store's searchable custom fields.
      - name: q[ascend_by_price]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `ascend_by_price`.
      - name: q[descend_by_price]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `descend_by_price`.
      - name: q[in_categories][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        description: Applies `in_categories` to the given value.
      - name: q[in_category]
        in: query
        required: false
        schema:
          type: string
        description: Applies `in_category` to the given value.
      - name: q[in_collection]
        in: query
        required: false
        schema:
          type: string
        description: Applies `in_collection` to the given value.
      - name: q[in_stock]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `in_stock`.
      - name: q[in_taxon]
        in: query
        required: false
        schema:
          type: string
        description: Applies `in_taxon` to the given value.
      - name: q[not_discontinued]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `not_discontinued`.
      - name: q[out_of_stock]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `out_of_stock`.
      - name: q[price_between][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: number
          minItems: 2
          maxItems: 2
        description: Applies `price_between` to the given value.
      - name: q[price_gte]
        in: query
        required: false
        schema:
          type: number
        description: Applies `price_gte` to the given value.
      - name: q[price_lte]
        in: query
        required: false
        schema:
          type: number
        description: Applies `price_lte` to the given value.
      - name: q[search_by_name]
        in: query
        required: false
        schema:
          type: string
        description: Applies `search_by_name` to the given value.
      - name: q[with_option_value_ids][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        description: Applies `with_option_value_ids` to the given value.
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `available_on` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `description` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `discontinue_on` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `price` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `seller_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `slug` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `status` | One of `draft`, `active`, `archived`, `proposed`, `rejected` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[categories_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `categories_` | `automatic`, `children_count`, `created_at`, `depth`, `id`, `name`, `parent_id`, `permalink`, `position`, `pretty_name`, `products_count`, `updated_at` |
          | `categories_parent_` | `automatic`, `children_count`, `created_at`, `depth`, `id`, `name`, `parent_id`, `permalink`, `position`, `pretty_name`, `products_count`, `updated_at` |
          | `channels_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `collections_` | `automatic`, `created_at`, `id`, `name`, `permalink`, `position`, `products_count`, `sort_order`, `updated_at` |
          | `default_variant_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `default_variant_option_values_` | `created_at`, `id`, `label`, `name`, `position`, `updated_at` |
          | `default_variant_prices_` | `amount`, `compare_at_amount`, `created_at`, `currency`, `id`, `min_quantity`, `price_list_id`, `updated_at`, `variant_id` |
          | `default_variant_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `default_variant_tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |
          | `labels_` | `created_at`, `id`, `name`, `updated_at` |
          | `option_types_` | `created_at`, `id`, `kind`, `label`, `name`, `position`, `updated_at` |
          | `product_categories_` | `category_id`, `created_at`, `id`, `position`, `product_id`, `updated_at` |
          | `product_type_` | `created_at`, `id`, `name`, `updated_at` |
          | `product_type_option_types_` | `created_at`, `id`, `kind`, `label`, `name`, `position`, `updated_at` |
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `store_` | `created_at`, `id`, `name`, `updated_at` |
          | `tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `variants_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `variants_option_values_` | `created_at`, `id`, `label`, `name`, `position`, `updated_at` |
          | `variants_prices_` | `amount`, `compare_at_amount`, `created_at`, `currency`, `id`, `min_quantity`, `price_list_id`, `updated_at`, `variant_id` |
          | `variants_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `variants_tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |

          </Accordion>

          **Sort by:** `available_on`, `created_at`, `description`, `discontinue_on`, `id`, `name`, `price`, `seller_id`, `slug`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Product
        sortable:
        - available_on
        - created_at
        - description
        - discontinue_on
        - id
        - name
        - price
        - seller_id
        - slug
        - status
        - updated_at
      responses:
        '200':
          description: products found
          content:
            application/json:
              example:
                data: []
                meta:
                  page: 1
                  limit: 25
                  count: 0
                  pages: 1
                  from: 0
                  to: 0
                  in: 0
                  previous:
                  next:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/Product"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Add products to a category
      tags:
      - Categories
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Classifies products under the category in bulk (appended to the end). Already-classified products are skipped; the count reports what was added.

        **Required scope:** `write_categories` (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 { added_count } = await client.categories.products.create('ctg_UkLWZg9DAJ', [
            'prod_UkLWZg9DAJ',
            'prod_9XbR2kQwLm',
          ])
      - lang: bash
        label: Spree CLI
        source: spree api post /categories/{category_id}/products -d '{ ... }'
      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: category_id
        in: path
        required: true
        description: Category ID
        schema:
          type: string
      responses:
        '201':
          description: products added
          content:
            application/json:
              example:
                added_count: 1
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductMembershipParams"
        required: true
    delete:
      summary: Remove products from a category
      tags:
      - Categories
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Removes products from the category's manual classification in bulk. Ids that are not classified are ignored; the count reports what was removed.

        **Required scope:** `write_categories` (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 { removed_count } = await client.categories.products.delete('ctg_UkLWZg9DAJ', [
            'prod_UkLWZg9DAJ',
          ])
      - lang: bash
        label: Spree CLI
        source: spree api delete /categories/{category_id}/products
      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: category_id
        in: path
        required: true
        description: Category ID
        schema:
          type: string
      responses:
        '200':
          description: products removed
          content:
            application/json:
              example:
                removed_count: 1
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductMembershipParams"
        required: true
  "/api/v3/admin/categories/{category_id}/products/{id}/reposition":
    patch:
      summary: Reposition a category product
      tags:
      - Categories
      operationId: categories_reposition_product
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Moves a product to a new index among the category's products.

        **Required scope:** `write_categories` (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',
          })

          // Moves the product to the top of the category; positions are 0-based.
          await client.categories.products.reposition('ctg_UkLWZg9DAJ', 'prod_UkLWZg9DAJ', {
            new_position: 0,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /categories/{category_id}/products/{id}/reposition
          -d '{"new_position":0}'
      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: category_id
        in: path
        required: true
        description: Category ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Product ID
        schema:
          type: string
      responses:
        '204':
          description: product repositioned
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductMembershipRepositionParams"
        required: true
  "/api/v3/admin/categories/{category_id}/custom_fields":
    get:
      summary: List category custom fields
      tags:
      - Categories
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the category's custom field values.

        **Required scope:** `read_categories` (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.categories.customFields.list('ctg_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /categories/{category_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: category_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/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).
      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: channels } = await client.channels.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /channels
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - name: page
        in: query
        required: false
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        schema:
          type: integer
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `active` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `default` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `store_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Channel
        sortable:
        - active
        - code
        - created_at
        - default
        - id
        - name
        - store_id
        - updated_at
      responses:
        '200':
          description: channels found
          content:
            application/json:
              example:
                data:
                - id: ch_UkLWZg9DAJ
                  name: Online Store
                  code: online
                  active: true
                  default: true
                  storefront_access:
                  guest_checkout:
                  created_at: '2026-11-11T12:45:25.454Z'
                  updated_at: '2026-11-11T12:45:25.454Z'
                  order_routing_strategy:
                  stock_location_ids: []
                  default_catalog_id:
                - id: ch_gbHJdmfrXB
                  name: Wholesale
                  code: wholesale
                  active: true
                  default: false
                  storefront_access:
                  guest_checkout:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  order_routing_strategy:
                  stock_location_ids: []
                  default_catalog_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/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).
      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',
          })

          // `code` is optional — when omitted it's derived from `name`
          // ("Point of Sale" → "point-of-sale").
          const channel = await client.channels.create({
            name: 'Point of Sale',
            code: 'pos',
            active: true,
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /channels -d '{"name":"Point of Sale","code":"pos","active":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: channel created
          content:
            application/json:
              example:
                id: ch_EfhxLZ9ck8
                name: Marketplace
                code: marketplace
                active: true
                default: false
                storefront_access:
                guest_checkout:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                order_routing_strategy:
                stock_location_ids: []
                default_catalog_id:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ChannelCreateParams"
        required: 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)."
      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 channel = await client.channels.get('channel_xxx')
      - lang: bash
        label: Spree CLI
        source: spree api get /channels/{id}
      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
                storefront_access:
                guest_checkout:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                order_routing_strategy:
                stock_location_ids: []
                default_catalog_id:
    patch:
      summary: Update a channel
      tags:
      - Channels
      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 channel = await client.channels.update('channel_xxx', {
            name: 'Wholesale (Updated)',
            active: false,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /channels/{id} -d '{"name":"Wholesale (Updated)","active":false}'
      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
                storefront_access: login_required
                guest_checkout: false
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                order_routing_strategy:
                stock_location_ids: []
                default_catalog_id:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ChannelUpdateParams"
        required: true
    delete:
      summary: Delete a channel
      tags:
      - Channels
      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.channels.delete('channel_xxx')
      - lang: bash
        label: Spree CLI
        source: spree api delete /channels/{id}
      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).
      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',
          })

          // Idempotent — re-publishing an already-published product updates its
          // publication window. `published_at`/`unpublished_at` are optional:
          // `null` (or omitted) means live immediately and never come down.
          const { product_count } = await client.channels.addProducts('channel_xxx', {
            product_ids: ['prod_xxx', 'prod_yyy'],
            published_at: '2026-07-01T00:00:00Z',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /channels/{id}/add_products -d '{"product_ids":["prod_xxx","prod_yyy"],"published_at":"2026-07-01T00:00:00Z"}'
      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:
              "$ref": "#/components/schemas/ChannelAddProductsParams"
        required: true
  "/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).
      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_count } = await client.channels.removeProducts('channel_xxx', {
            product_ids: ['prod_xxx', 'prod_yyy'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /channels/{id}/remove_products -d '{"product_ids":["prod_xxx","prod_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: products unpublished
          content:
            application/json:
              example:
                product_count: 1
              schema:
                type: object
                properties:
                  product_count:
                    type: integer
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ChannelRemoveProductsParams"
        required: true
  "/api/v3/admin/channels/{channel_id}/order_routing_rules":
    parameters:
    - name: channel_id
      in: path
      required: true
      schema:
        type: string
    get:
      summary: List order routing rules for a channel
      tags:
      - Channels
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the channel's routing rules in priority order. The rules engine walks them top-down; see the Order Routing guide.

        **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: rules } = await client.channels.orderRoutingRules.list('ch_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /channels/{channel_id}/order_routing_rules
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[active_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `active` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `channel_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `store_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `type` | Type | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `active`, `channel_id`, `created_at`, `id`, `position`, `store_id`, `type`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: OrderRoutingRule
        sortable:
        - active
        - channel_id
        - created_at
        - id
        - position
        - store_id
        - type
        - updated_at
      responses:
        '200':
          description: rules found
          content:
            application/json:
              example:
                data:
                - id: orule_UkLWZg9DAJ
                  position: 1
                  active: true
                  created_at: '2026-11-11T12:45:25.458Z'
                  updated_at: '2026-11-11T12:45:25.458Z'
                  type: preferred_location
                  channel_id: ch_UkLWZg9DAJ
                  preferences: {}
                - id: orule_gbHJdmfrXB
                  position: 2
                  active: true
                  created_at: '2026-11-11T12:45:25.461Z'
                  updated_at: '2026-11-11T12:45:25.461Z'
                  type: minimize_splits
                  channel_id: ch_UkLWZg9DAJ
                  preferences: {}
                - id: orule_EfhxLZ9ck8
                  position: 3
                  active: true
                  created_at: '2026-11-11T12:45:25.464Z'
                  updated_at: '2026-11-11T12:45:25.464Z'
                  type: default_location
                  channel_id: ch_UkLWZg9DAJ
                  preferences: {}
                meta:
                  page: 1
                  limit: 25
                  count: 3
                  pages: 1
                  from: 1
                  to: 3
                  in: 3
                  previous:
                  next:
    post:
      summary: Create an order routing rule on a channel
      tags:
      - Channels
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds a rule to the channel's routing list. The `type` is the wire shorthand from `GET /order_routing_rules/types` (e.g. `preferred_location`). Omitting `position` appends the rule at the end of the list. Each rule kind can appear at most once per channel — a duplicate `type` is rejected 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',
          })

          const rule = await client.channels.orderRoutingRules.create('ch_UkLWZg9DAJ', {
            type: 'preferred_location',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /channels/{channel_id}/order_routing_rules -d '{"type":"preferred_location"}'
      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
          content:
            application/json:
              example:
                id: orule_VqXmZF31wY
                position: 3
                active: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: default_location
                channel_id: ch_UkLWZg9DAJ
                preferences: {}
        '422':
          description: unknown rule type
          content:
            application/json:
              example:
                error:
                  code: unknown_order_routing_rule_type
                  message: Unknown type
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/OrderRoutingRuleCreateParams"
        required: true
  "/api/v3/admin/channels/{channel_id}/order_routing_rules/{id}":
    parameters:
    - name: channel_id
      in: path
      required: true
      schema:
        type: string
    - name: id
      in: path
      required: true
      schema:
        type: string
    patch:
      summary: Update an order routing rule
      tags:
      - Channels
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Updates a rule's `active` flag, `position` (the list reorders around it), or `preferences`. The rule kind cannot be changed — delete and re-create instead.

        **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 rule = await client.channels.orderRoutingRules.update('ch_UkLWZg9DAJ', 'orule_k5nR8xLq', {
            active: false,
            position: 2,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /channels/{channel_id}/order_routing_rules/{id} -d
          '{"active":false,"position":2}'
      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: orule_UkLWZg9DAJ
                position: 2
                active: false
                created_at: '2026-11-11T12:45:25.458Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: preferred_location
                channel_id: ch_UkLWZg9DAJ
                preferences: {}
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/OrderRoutingRuleUpdateParams"
        required: true
    delete:
      summary: Delete an order routing rule
      tags:
      - Channels
      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.channels.orderRoutingRules.delete('ch_UkLWZg9DAJ', 'orule_k5nR8xLq')
      - lang: bash
        label: Spree CLI
        source: spree api delete /channels/{channel_id}/order_routing_rules/{id}
      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/order_routing_rules/types":
    get:
      summary: List available order routing rule types
      tags:
      - Channels
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Enumerates the registered rule kinds with their labels, descriptions and preference schemas — drives the "Add rule" picker in the admin dashboard. Plugins extend the list by registering `Spree::OrderRoutingRule` subclasses via `Spree.order_routing.rules`.

        **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: ruleTypes } = await client.orderRoutingRules.types()
      - lang: bash
        label: Spree CLI
        source: spree api get /order_routing_rules/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: types found
          content:
            application/json:
              example:
                data:
                - type: default_location
                  label: Default location
                  description: Prefer the stock location marked as default
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: minimize_splits
                  label: Minimize splits
                  description: Prefer the location that can fulfill the most items
                    on its own, avoiding split shipments
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: preferred_location
                  label: Preferred location
                  description: Fulfill from the location pinned on the order, when
                    one is set
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
  "/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]=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({
            resource_type_eq: 'product',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /custom_field_definitions -d '{"resource_type_eq":"product"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of namespace, key, and label (partial, case-insensitive).
      - 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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[key_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `field_type` | Type | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `key` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `label` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `namespace` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `resource_type` | Type | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `searchable` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `sortable` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `storefront_visible` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `field_type`, `id`, `key`, `label`, `namespace`, `resource_type`, `searchable`, `sortable`, `storefront_visible`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomFieldDefinition
        sortable:
        - created_at
        - field_type
        - id
        - key
        - label
        - namespace
        - resource_type
        - searchable
        - sortable
        - storefront_visible
        - updated_at
      responses:
        '200':
          description: definitions returned
          content:
            application/json:
              example:
                data:
                - id: cfdef_UkLWZg9DAJ
                  namespace: specs
                  key: fabric
                  label: Title
                  field_type: short_text
                  storefront_visible: true
                  searchable: false
                  sortable: false
                  filter_key: cf_specs_fabric
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  resource_type: product
                - id: cfdef_gbHJdmfrXB
                  namespace: custom
                  key: order_notes
                  label: Order Notes
                  field_type: short_text
                  storefront_visible: true
                  searchable: false
                  sortable: false
                  filter_key: cf_custom_order_notes
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  resource_type: order
                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: 'product',
            storefront_visible: true,
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /custom_field_definitions -d '{"namespace":"specs","key":"origin","label":"Country
          of Origin","field_type":"short_text","resource_type":"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
                storefront_visible: true
                searchable: false
                sortable: false
                filter_key: cf_specs_origin
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                resource_type: product
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CustomFieldDefinitionCreateParams"
        required: true
  "/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)."
      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.get('cfd_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /custom_field_definitions/{id}
      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
                storefront_visible: true
                searchable: false
                sortable: false
                filter_key: cf_specs_fabric
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                resource_type: product
    patch:
      summary: Update 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.update('cfd_UkLWZg9DAJ', {
            label: 'Country of Origin',
            storefront_visible: false,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /custom_field_definitions/{id} -d '{"label":"Country
          of Origin","storefront_visible":false}'
      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
                storefront_visible: false
                searchable: false
                sortable: false
                filter_key: cf_specs_fabric
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                resource_type: product
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CustomFieldDefinitionUpdateParams"
        required: true
    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).
      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.customFieldDefinitions.delete('cfd_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /custom_field_definitions/{id}
      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 })
      - lang: bash
        label: Spree CLI
        source: spree api get /customer_groups -d '{"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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - 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
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `name`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomerGroup
        sortable:
        - created_at
        - id
        - name
        - updated_at
      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-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                - id: cg_gbHJdmfrXB
                  name: Wholesale
                  description:
                  customers_count: 0
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /customer_groups -d '{"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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              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:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CustomerGroupCreateParams"
        required: true
  "/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'] })
      - lang: bash
        label: Spree CLI
        source: spree api get /customer_groups/{id} -d '{"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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                customers:
                - id: cust_UkLWZg9DAJ
                  email: lucienne@nitzsche.name
                  first_name: Dan
                  last_name: Ebert
                  phone:
                  accepts_email_marketing: false
                  email_marketing_consent_updated_at: '2026-01-15T12:00:00Z'
                  full_name: Dan Ebert
                  available_store_credit_total: '0.00'
                  failed_attempts: 0
                  metadata: {}
                  email_marketing_consent_source: unknown
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  anonymized_at:
                  anonymized: false
                  tags: []
                  internal_note:
                  internal_note_html:
                  default_billing_address_id:
                  default_shipping_address_id:
                  orders_count: 0
                  total_spent: '0.00'
                  last_order_completed_at:
                  customer_group_ids:
                  - cg_UkLWZg9DAJ
              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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /customer_groups/{id} -d '{"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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              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:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CustomerGroupUpdateParams"
        required: true
    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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /customer_groups/{id}
      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}/custom_fields":
    get:
      summary: List customer custom fields
      tags:
      - Customers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the customer's custom field values.

        **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: customFields } = await client.customers.customFields.list('cus_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /customers/{customer_id}/custom_fields
      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., 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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/customers/{id}/export":
    get:
      summary: Export a customer's personal data
      tags:
      - Customers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns everything the store holds about this customer, for answering a
        GDPR right-of-access request (Art. 15) that reached the merchant
        directly.


        **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',
          })

          // Everything the store holds about the customer, to answer a GDPR access request:
          const customerData = await client.customers.export('cus_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /customers/{id}/export
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: customer data
          content:
            application/json:
              example:
                account:
                  id: cust_UkLWZg9DAJ
                  email: jane@example.com
                  first_name: Jane
                  last_name: Doe
                  phone:
                  selected_locale:
                  tags: []
                  metadata:
                  internal_note:
                  created_at: '2026-01-15T12:00:00Z'
                  anonymized_at:
                marketing_consent:
                  accepts_email_marketing: false
                  consent_updated_at: '2026-01-15T12:00:00Z'
                  consent_source: unknown
                  newsletter_subscriptions: []
                consent_records: []
                addresses: []
                orders: []
                draft_orders: []
                order_groups: []
                carts: []
                payment_sources: []
                connected_logins: []
                store_credits: []
                gift_cards: []
                wishlists: []
                custom_fields: []
                companies: []
                tax_identifiers: []
                exported_at: '2026-01-15T12:00:00Z'
              schema:
                type: object
                properties:
                  account:
                    type: object
                  marketing_consent:
                    type: object
                  consent_records:
                    type: array
                    items:
                      type: object
                  addresses:
                    type: array
                    items:
                      type: object
                  orders:
                    type: array
                    items:
                      type: object
                  exported_at:
                    type: string
        '404':
          description: not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Customer not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/customers/{id}/anonymize":
    post:
      summary: Erase a customer's personal data
      tags:
      - Customers
      x-spree-agent: false
      x-spree-agent-reason: Irreversible erasure of a person's data under GDPR Art.
        17, which is not something to offer a model behind one confirmation prompt.
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Carries out a GDPR right-to-erasure request (Art. 17). Personal data is
        replaced across the account, its addresses, the address snapshots on
        past orders, saved cards, connected identities and live sessions.

        Orders, payments and tax records are kept — they carry their own
        retention obligation — with the personal details removed. The country,
        state and a truncated postal code survive on order addresses so the tax
        jurisdiction of a past sale stays provable.

        Irreversible.


        **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',
          })

          // Irreversible: personal data is erased, orders and payments are kept.
          const customer = await client.customers.anonymize('cus_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api post /customers/{id}/anonymize -d '{ ... }'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: customer anonymized
          content:
            application/json:
              example:
                id: cust_UkLWZg9DAJ
                email: anonymized-87c6bfa6-4803-420c-a5e2-b1c962f0f40a@invalid
                first_name: Redacted
                last_name: Redacted
                phone:
                accepts_email_marketing: false
                email_marketing_consent_updated_at: '2026-01-15T12:00:00Z'
                full_name: Redacted Redacted
                available_store_credit_total: '0.00'
                failed_attempts: 0
                metadata: {}
                email_marketing_consent_source: anonymization
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                anonymized_at: '2026-01-15T12:00:00Z'
                anonymized: true
                tags: []
                internal_note:
                internal_note_html:
                default_billing_address_id:
                default_shipping_address_id:
                orders_count: 0
                total_spent: '0.00'
                last_order_completed_at:
                customer_group_ids: []
              schema:
                type: object
                properties:
                  id:
                    type: string
                  email:
                    type: string
                  anonymized:
                    type: boolean
                  anonymized_at:
                    type: string
                    nullable: true
  "/api/v3/admin/consent_records":
    get:
      summary: List consent records
      tags:
      - Customers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the consents customers gave or withdrew, newest first, as evidence of what each one agreed to and when.

        **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: consentRecords } = await client.consentRecords.list({
            email_eq: 'jane@example.com',
            sort: '-recorded_at',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /consent_records -d '{"email_eq":"jane@example.com","sort":"-recorded_at"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[email_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `accepted` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `email` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `purpose` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `recorded_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `source` | One of `checkout`, `registration`, `account`, `admin`, `newsletter`, `anonymization`, `unknown`, `import`, `storefront` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `accepted`, `created_at`, `email`, `id`, `purpose`, `recorded_at`, `source`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: ConsentRecord
        sortable:
        - accepted
        - created_at
        - email
        - id
        - purpose
        - recorded_at
        - source
        - updated_at
      responses:
        '200':
          description: consent records found
          content:
            application/json:
              example:
                data:
                - id: consent_UkLWZg9DAJ
                  purpose: terms_of_service
                  source: registration
                  accepted: true
                  email: jane@example.com
                  ip_address:
                  created_at: '2026-01-15T12:00:00.000Z'
                  recorded_at: '2026-01-15T12:00:00Z'
                  documents: []
                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/ConsentRecord"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/data_requests":
    get:
      summary: List data requests
      tags:
      - Customers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the requests customers made to export or erase their personal data, newest first.

        **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: dataRequests } = await client.dataRequests.list({
            kind_eq: 'erasure',
            sort: '-requested_at',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /data_requests -d '{"kind_eq":"erasure","sort":"-requested_at"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[access]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `access`.
      - name: q[erasure]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `erasure`.
      - name: q[in_progress]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `in_progress`.
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `completed_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `email` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `kind` | One of `access`, `erasure` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `requested_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `status` | One of `awaiting_confirmation`, `pending`, `processing`, `completed`, `failed`, `lapsed` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `completed_at`, `created_at`, `email`, `id`, `kind`, `number`, `requested_at`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: DataRequest
        sortable:
        - completed_at
        - created_at
        - email
        - id
        - kind
        - number
        - requested_at
        - status
        - updated_at
      responses:
        '200':
          description: data requests found
          content:
            application/json:
              example:
                data:
                - id: dsr_UkLWZg9DAJ
                  number: DSR1001
                  kind: access
                  status: pending
                  requested_at: '2026-01-15T12:00:00Z'
                  completed_at:
                  expires_at:
                  email: jane@example.com
                  error_message:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  customer_id: cust_UkLWZg9DAJ
                  requested_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/DataRequest"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Record a data request
      tags:
      - Customers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Records a request a customer made to the merchant directly, to export
        or erase their personal data, and starts answering it. A request of the
        same kind already in progress for the customer is returned instead of a
        second one.


        **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 dataRequest = await client.dataRequests.create({
            customer_id: 'cus_UkLWZg9DAJ',
            kind: 'access',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /data_requests -d '{"customer_id":"cus_UkLWZg9DAJ","kind":"access"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      responses:
        '202':
          description: data request recorded
          content:
            application/json:
              example:
                id: dsr_UkLWZg9DAJ
                number: DSR1001
                kind: access
                status: pending
                requested_at: '2026-01-15T12:00:00Z'
                completed_at:
                expires_at:
                email: jane@example.com
                error_message:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                customer_id: cust_UkLWZg9DAJ
                requested_by_id: adm_UkLWZg9DAJ
              schema:
                "$ref": "#/components/schemas/DataRequest"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DataRequestCreateParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /customers/{customer_id}/addresses
      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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[address1_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `address1` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `address2` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `city` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `company` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `country_code` | One of the `CountryCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `first_name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `last_name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `phone` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `postal_code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `state_code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Address
        sortable:
        - address1
        - address2
        - city
        - company
        - country_code
        - created_at
        - first_name
        - id
        - last_name
        - phone
        - postal_code
        - state_code
        - updated_at
      responses:
        '200':
          description: addresses found
          content:
            application/json:
              example:
                data:
                - id: addr_UkLWZg9DAJ
                  label:
                  first_name: John
                  last_name: Doe
                  full_name: John Doe
                  address1: 29 Lovely Street
                  address2: Northwest
                  postal_code: '10118'
                  city: New York
                  phone: 555-555-0199
                  company: Company
                  country_name: United States
                  country_code: US
                  state_text: NY
                  state_code: NY
                  quick_checkout: false
                  is_default_billing: false
                  is_default_shipping: false
                  state_name: New York
                  owner:
                    id: cust_UkLWZg9DAJ
                    type: customer
                    name:
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  latitude:
                  longitude:
                  customer_id: cust_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_code: 'US',
            state_code: 'NY',
            phone: '+1 212 555 1234',
            label: 'Office',
            is_default_shipping: true,
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /customers/{customer_id}/addresses -d '{"first_name":"Jane","last_name":"Doe","address1":"350
          Fifth Avenue","city":"New York","postal_code":"10118","country_code":"US","state_code":"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
                label: Office
                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
                country_code: US
                state_text: NY
                state_code: NY
                quick_checkout: false
                is_default_billing: false
                is_default_shipping: false
                state_name: New York
                owner:
                  id: cust_UkLWZg9DAJ
                  type: customer
                  name:
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                latitude:
                longitude:
                customer_id: cust_UkLWZg9DAJ
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CustomerAddressCreateParams"
        required: true
  "/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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /customers/{customer_id}/addresses/{id} -d '{"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
                label:
                first_name: John
                last_name: Doe
                full_name: John Doe
                address1: 31 Lovely Street
                address2: Northwest
                postal_code: '10118'
                city: Manhattan
                phone: 555-555-0199
                company: Company
                country_name: United States
                country_code: US
                state_text: NY
                state_code: NY
                quick_checkout: false
                is_default_billing: false
                is_default_shipping: false
                state_name: New York
                owner:
                  id: cust_UkLWZg9DAJ
                  type: customer
                  name:
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                latitude:
                longitude:
                customer_id: cust_UkLWZg9DAJ
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CustomerAddressUpdateParams"
        required: true
    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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /customers/{customer_id}/addresses/{id}
      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')
      - lang: bash
        label: Spree CLI
        source: spree api get /customers/{customer_id}/credit_cards
      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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `name`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CreditCard
        sortable:
        - created_at
        - id
        - name
        - updated_at
      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: cust_UkLWZg9DAJ
                  payment_method_id: pm_UkLWZg9DAJ
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                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')
      - lang: bash
        label: Spree CLI
        source: spree api get /customers/{customer_id}/credit_cards/{id}
      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: cust_UkLWZg9DAJ
                payment_method_id: pm_UkLWZg9DAJ
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
    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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /customers/{customer_id}/credit_cards/{id}
      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')
      - lang: bash
        label: Spree CLI
        source: spree api get /customers/{customer_id}/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: customer_id
        in: path
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of memo (partial, case-insensitive).
      - name: q[from_gift_card]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `from_gift_card`.
      - name: q[outstanding]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `outstanding`.
      - name: expand
        in: query
        required: false
        description: Comma-separated associations to expand (e.g., 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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[memo_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `amount` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_by_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `currency` | One of the `CurrencyCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `customer_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `memo` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[customer_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `customer_addresses_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customer_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customer_customer_groups_` | `created_at`, `id`, `name`, `updated_at` |
          | `customer_orders_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `customer_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customer_spree_roles_` | `created_at`, `id`, `name`, `updated_at` |
          | `customer_tags_` | `created_at`, `id`, `name`, `updated_at` |

          </Accordion>

          **Sort by:** `amount`, `created_at`, `created_by_id`, `currency`, `customer_id`, `id`, `memo`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: StoreCredit
        sortable:
        - amount
        - created_at
        - created_by_id
        - currency
        - customer_id
        - id
        - memo
        - updated_at
      responses:
        '200':
          description: store credits found
          content:
            application/json:
              example:
                data:
                - id: credit_UkLWZg9DAJ
                  amount: '50.00'
                  amount_used: '0.00'
                  amount_remaining: '50.00'
                  currency: USD
                  memo:
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  amount_authorized: '0.00'
                  outstanding: true
                  customer_id: cust_UkLWZg9DAJ
                  created_by_id: adm_UkLWZg9DAJ
                  created_by_type: admin_user
                  originator_type:
                  originator_id:
                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',
            memo: 'Goodwill credit',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /customers/{customer_id}/store_credits -d '{"amount":"25.00","currency":"USD","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.00'
                amount_used: '0.00'
                amount_remaining: '25.00'
                currency: USD
                memo: Goodwill
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                amount_authorized: '0.00'
                outstanding: true
                customer_id: cust_UkLWZg9DAJ
                created_by_id: adm_gbHJdmfrXB
                created_by_type: admin_user
                originator_type:
                originator_id:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CustomerStoreCreditCreateParams"
        required: true
  "/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 / 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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /customers/{customer_id}/store_credits/{id} -d '{"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.00'
                amount_used: '0.00'
                amount_remaining: '50.00'
                currency: USD
                memo: Updated
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                amount_authorized: '0.00'
                outstanding: true
                customer_id: cust_UkLWZg9DAJ
                created_by_id: adm_UkLWZg9DAJ
                created_by_type: admin_user
                originator_type:
                originator_id:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CustomerStoreCreditUpdateParams"
        required: true
    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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /customers/{customer_id}/store_credits/{id}
      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/{customer_id}/tax_identifiers":
    get:
      summary: List customer tax registrations
      tags:
      - Customers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the customer's own tax registrations, one per kind.

        **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: registrations } = await client.customers.taxIdentifiers.list('cus_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /customers/{customer_id}/tax_identifiers
      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: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: TaxIdentifier
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: registrations found
          content:
            application/json:
              example:
                data:
                - id: txi_UkLWZg9DAJ
                  kind: eu_vat
                  value: DE100000016
                  validation_status:
                  validation_evidence:
                  source:
                  validated_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  validatable: false
                  customer_id: cust_UkLWZg9DAJ
                  cart_id:
                  order_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/TaxIdentifier"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/customers/{customer_id}/tax_identifiers/{id}":
    patch:
      summary: Update a customer tax registration
      tags:
      - Customers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Corrects a registration number. A changed number is checked again before it counts as verified.

        **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 registration = await client.customers.taxIdentifiers.update(
            'cus_UkLWZg9DAJ',
            'txi_UkLWZg9DAJ',
            { value: 'DE123456789' },
          )
      - lang: bash
        label: Spree CLI
        source: spree api patch /customers/{customer_id}/tax_identifiers/{id} -d '{"value":"DE123456789"}'
      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: registration updated
          content:
            application/json:
              example:
                id: txi_UkLWZg9DAJ
                kind: eu_vat
                value: DE100000008
                validation_status:
                validation_evidence:
                source:
                validated_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                validatable: false
                customer_id: cust_UkLWZg9DAJ
                cart_id:
                order_id:
              schema:
                "$ref": "#/components/schemas/TaxIdentifier"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaxIdentifierUpdateParams"
        required: true
  "/api/v3/admin/customers/{customer_id}/tax_identifiers/{id}/validate":
    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
    post:
      summary: Re-check a customer tax registration
      tags:
      - 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 registration = await client.customers.taxIdentifiers.validate(
            'cust_UkLWZg9DAJ',
            'txi_UkLWZg9DAJ',
          )
      - lang: bash
        label: Spree CLI
        source: spree api post /customers/{customer_id}/tax_identifiers/{id}/validate
          -d '{ ... }'
      operationId: customer_tax_identifiers_validate
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Asks the registry again. Manual because a registry answers only "valid now" — a number verified
        last year may have been deregistered since — and because a check that came back unavailable
        cannot otherwise be retried without editing the number.


        **Required scope:** `write_customers` (for API-key authentication).
      responses:
        '202':
          description: registry check queued
          content:
            application/json:
              example:
                id: txi_UkLWZg9DAJ
                kind: eu_vat
                value: DE100000032
                validation_status: pending
                validation_evidence:
                source:
                validated_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                validatable: true
                customer_id: cust_UkLWZg9DAJ
                cart_id:
                order_id:
              schema:
                "$ref": "#/components/schemas/TaxIdentifier"
        '422':
          description: no validator installed for this kind
          content:
            application/json:
              example:
                error:
                  code: tax_id_not_validatable
                  message: No registry validator is installed for tax identifier kind
                    'eu_vat'
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/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,
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /customers -d '{"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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches email, first name, last name or full name (partial, case-insensitive).
      - name: q[anonymized]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `anonymized`.
      - name: q[with_min_total_spent]
        in: query
        required: false
        schema:
          type: number
        description: Applies `with_min_total_spent` to the given value.
      - name: q[with_standing_for_company][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        description: Applies `with_standing_for_company` to the given value.
      - name: page
        in: query
        required: false
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        schema:
          type: integer
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - 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
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[email_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `accepts_email_marketing` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `email` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `first_name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `last_name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `phone` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[addresses_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `addresses_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customer_groups_` | `created_at`, `id`, `name`, `updated_at` |
          | `orders_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `orders_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `orders_channel_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `orders_fulfillments_` | `created_at`, `id`, `number`, `updated_at` |
          | `orders_line_items_` | `additional_tax_total`, `adjustment_total`, `cost_price`, `created_at`, `discount_total`, `id`, `included_tax_total`, `non_taxable_adjustment_total`, `order_id`, `pre_tax_amount`, `price`, `quantity`, `tax_category_id`, `taxable_adjustment_total`, `updated_at`, `variant_id` |
          | `orders_order_group_` | `created_at`, `currency`, `email`, `id`, `number`, `updated_at` |
          | `orders_promotions_` | `code`, `created_at`, `expires_at`, `id`, `kind`, `name`, `path`, `promotion_category_id`, `starts_at`, `updated_at` |
          | `orders_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `orders_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `orders_shipments_` | `created_at`, `id`, `number`, `updated_at` |
          | `orders_store_` | `created_at`, `id`, `name`, `updated_at` |
          | `orders_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `spree_roles_` | `created_at`, `id`, `name`, `updated_at` |
          | `tags_` | `created_at`, `id`, `name`, `updated_at` |

          </Accordion>

          **Sort by:** `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Customer
        sortable:
        - accepts_email_marketing
        - created_at
        - email
        - first_name
        - id
        - last_name
        - phone
        - updated_at
      responses:
        '200':
          description: customers found
          content:
            application/json:
              example:
                data:
                - id: cust_UkLWZg9DAJ
                  email: jane@example.com
                  first_name: Jane
                  last_name: Doe
                  phone:
                  accepts_email_marketing: false
                  email_marketing_consent_updated_at: '2026-01-15T12:00:00Z'
                  full_name: Jane Doe
                  available_store_credit_total: '0.00'
                  failed_attempts: 0
                  metadata: {}
                  email_marketing_consent_source: unknown
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  anonymized_at:
                  anonymized: false
                  tags: []
                  internal_note:
                  internal_note_html:
                  default_billing_address_id:
                  default_shipping_address_id:
                  orders_count: 0
                  total_spent: '0.00'
                  last_order_completed_at:
                  customer_group_ids: []
                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,
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /customers -d '{"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: cust_gbHJdmfrXB
                email: newcustomer@example.com
                first_name: New
                last_name: Customer
                phone:
                accepts_email_marketing: false
                email_marketing_consent_updated_at: '2026-01-15T12:00:00Z'
                full_name: New Customer
                available_store_credit_total: '0.00'
                failed_attempts: 0
                metadata: {}
                email_marketing_consent_source: unknown
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                anonymized_at:
                anonymized: false
                tags: []
                internal_note:
                internal_note_html:
                default_billing_address_id:
                default_shipping_address_id:
                orders_count: 0
                total_spent: '0.00'
                last_order_completed_at:
                customer_group_ids: []
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CustomerCreateParams"
        required: true
  "/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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /customers/{id} -d '{"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: cust_UkLWZg9DAJ
                email: jane@example.com
                first_name: Jane
                last_name: Doe
                phone:
                accepts_email_marketing: false
                email_marketing_consent_updated_at: '2026-01-15T12:00:00Z'
                full_name: Jane Doe
                available_store_credit_total: '0.00'
                failed_attempts: 0
                metadata: {}
                email_marketing_consent_source: unknown
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                anonymized_at:
                anonymized: false
                tags: []
                internal_note:
                internal_note_html:
                default_billing_address_id:
                default_shipping_address_id:
                orders_count: 0
                total_spent: '0.00'
                last_order_completed_at:
                customer_group_ids: []
    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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /customers/{id} -d '{"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: cust_UkLWZg9DAJ
                email: jane@example.com
                first_name: Updated
                last_name: Doe
                phone:
                accepts_email_marketing: false
                email_marketing_consent_updated_at: '2026-01-15T12:00:00Z'
                full_name: Updated Doe
                available_store_credit_total: '0.00'
                failed_attempts: 0
                metadata: {}
                email_marketing_consent_source: unknown
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                anonymized_at:
                anonymized: false
                tags: []
                internal_note:
                internal_note_html:
                default_billing_address_id:
                default_shipping_address_id:
                orders_count: 0
                total_spent: '0.00'
                last_order_completed_at:
                customer_group_ids: []
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CustomerUpdateParams"
        required: true
    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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /customers/{id}
      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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /customers/bulk_add_to_groups -d '{"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:
              "$ref": "#/components/schemas/CustomerBulkGroupsParams"
        required: true
  "/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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /customers/bulk_remove_from_groups -d '{"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:
              "$ref": "#/components/schemas/CustomerBulkGroupsParams"
        required: true
  "/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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /customers/bulk_add_tags -d '{"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:
              "$ref": "#/components/schemas/BulkTagsParams"
        required: true
  "/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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /customers/bulk_remove_tags -d '{"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:
              "$ref": "#/components/schemas/BulkTagsParams"
        required: true
  "/api/v3/admin/email_templates":
    get:
      summary: List email templates
      tags:
      - Email Templates
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns every email template merchants may edit: the emails customers
        receive, the email layout and the shared partials. Each shows what
        customers receive now (the store's published version, else Spree's
        default) and any draft in progress. Staff emails are not editable.


        **Required scope:** `read_email_templates` (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 templates = await client.emailTemplates.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /email_templates
      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: language
        in: query
        required: false
        description: A language code, or `any` (the default) for the version every
          language uses
        schema:
          type: string
      responses:
        '200':
          description: email templates found
          content:
            application/json:
              example:
                data:
                - id: spree.order_mailer.confirm_email
                  key: spree/order_mailer/confirm_email
                  subject: Order {{ order.number }} confirmed
                  body: "<mj-section><mj-column><mj-text>Thanks for your order, {{
                    order.customer_name }}!</mj-text></mj-column></mj-section>\n"
                  language: any
                  customized_languages: []
                  kind: email
                  customized: false
                  published_at:
                  default_subject: Order {{ order.number }} confirmed
                  default_body: "<mj-section><mj-column><mj-text>Thanks for your order,
                    {{ order.customer_name }}!</mj-text></mj-column></mj-section>\n"
                  published_language:
                  default_changed: false
                  base_subject:
                  base_body:
                  draft:
                - id: layouts.spree.base_mailer
                  key: layouts/spree/base_mailer
                  subject:
                  body: |
                    {% assign brand = store.branding %}<mjml lang="{{ locale }}">
                      <mj-head>
                        <mj-title>{{ subject }}</mj-title>
                        {% if brand.font_url %}<mj-font name="{{ brand.font_family | split: ',' | first }}" href="{{ brand.font_url }}" />{% endif %}
                        <mj-attributes>
                          <mj-all font-family="{{ brand.font_family }}" />
                          <mj-section padding="0" />
                          <mj-column padding="0" />
                          <mj-text padding="0" color="{{ brand.text_color }}" font-size="14px" line-height="1.6" align="center" />
                          <mj-button background-color="{{ brand.button_color }}" border="{{ brand.button_border }}" border-radius="8px" color="{{ brand.button_text_color }}" font-size="15px" font-weight="500" line-height="1.6" inner-padding="12px 20px" padding="32px 0 0" />
                          <mj-table padding="0" color="{{ brand.text_color }}" font-size="14px" line-height="1.6" />
                          <mj-class name="heading" font-family="{{ brand.heading_font_family }}" font-size="40px" font-weight="700" line-height="1.2" letter-spacing="-0.8px" color="{{ brand.heading_color }}" css-class="heading" />
                          <mj-class name="greeting" padding="24px 0 0" font-size="15px" font-weight="500" color="{{ brand.heading_color }}" />
                          <mj-class name="lead" padding="12px 0 0" />
                          <mj-class name="note" padding="24px 0 0" font-size="13px" css-class="note" />
                          <mj-class name="section-heading" padding="48px 0 16px" font-family="{{ brand.heading_font_family }}" font-size="16px" font-weight="500" letter-spacing="-0.16px" align="left" />
                          <mj-class name="body" padding="16px 0 0" align="left" />
                          <mj-class name="footer" padding="12px 0 0" font-size="11px" line-height="1.5" />
                        </mj-attributes>
                        <mj-style>
                          {% if brand.font == 'inter' %}
                          @font-face { font-family: "Geist"; font-style: normal; font-weight: 500 700; src: url("https://fonts.gstatic.com/s/geist/v4/gyByhwUxId8gMEwcGFU.woff2") format("woff2"); }
                          @font-face { font-family: "Inter"; font-style: normal; font-weight: 400 450; src: url("https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuOKfMZg.ttf") format("truetype"); }
                          @font-face { font-family: "Inter"; font-style: normal; font-weight: 500; src: url("https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuI6fMZg.ttf") format("truetype"); }
                          @font-face { font-family: "Inter"; font-style: normal; font-weight: 600; src: url("https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuGKYMZg.ttf") format("truetype"); }
                          {% endif %}
                          a { color: {{ brand.link_color }}; }
                          .hero > table { max-width: 420px; margin: 0 auto; }
                          .note a { color: {{ brand.text_color }}; word-break: break-all; }
                          .footer a { color: {{ brand.text_color }}; }
                          .item { width: 100%; background-color: #F0F0F0; border-radius: 16px; margin: 0 0 8px; }
                          .item_image { padding: 8px; width: 96px; }
                          .item_thumb { display: block; width: 80px; height: auto; border-radius: 12px; }
                          .item_thumb_placeholder { width: 80px; height: 80px; background-color: #E4E4E4; border-radius: 12px; }
                          .item_info { padding: 8px 16px 8px 8px; }
                          .item_name { font-size: 15px; line-height: 1.5; font-weight: 500; color: {{ brand.heading_color }}; text-decoration: none; }
                          .item_meta { margin: 2px 0 0; font-size: 13px; line-height: 1.5; color: {{ brand.text_color }}; }
                          .item_amount { padding: 8px 16px 8px 8px; text-align: right; white-space: nowrap; }
                          .item_qty { margin: 0; font-size: 13px; line-height: 1.5; color: {{ brand.text_color }}; }
                          .item_price { margin: 2px 0 0; font-size: 15px; line-height: 1.5; font-weight: 500; color: {{ brand.heading_color }}; }
                          .summary td { padding: 6px 0; font-size: 14px; line-height: 1.6; color: {{ brand.text_color }}; }
                          .summary_value { font-size: 15px; font-weight: 500; text-align: right; white-space: nowrap; color: {{ brand.heading_color }}; }
                          .summary_sub { display: block; font-size: 13px; line-height: 1.5; }
                          .summary_total td { padding: 14px 0 0; border-top: 1px solid #E8E9E9; font-weight: 500; color: {{ brand.heading_color }}; }
                          .summary_total .summary_value { font-weight: 600; }
                          .mailer_hero h1 { margin: 0; font-family: {{ brand.heading_font_family }}; font-size: 40px; line-height: 1.2; letter-spacing: -0.8px; font-weight: 700; color: {{ brand.heading_color }}; }
                          .mailer_hero p { margin: 12px 0 0; }
                          .mailer_hero .greeting { margin-top: 24px; font-size: 15px; font-weight: 500; color: {{ brand.heading_color }}; }
                          .mailer_hero .sub { margin-top: 24px; font-size: 13px; }
                          @media only screen and (max-width: 600px) {
                            .heading div { font-size: 32px !important; letter-spacing: -0.64px !important; }
                          }
                        </mj-style>
                      </mj-head>
                      <mj-body background-color="{{ brand.background_color }}" width="640px">
                        <mj-wrapper background-color="{{ brand.card_color }}" padding="56px 24px">
                          <mj-section padding="0 0 32px">
                            <mj-column>
                              {% if store.logo_url and store.logo_width %}
                                <mj-image src="{{ store.logo_url }}" href="{{ store.url }}" alt="{{ store.name }}" width="{{ store.logo_width }}px" height="32px" padding="0" />
                              {% elsif store.logo_url %}
                                <mj-text><a href="{{ store.url }}"><img src="{{ store.logo_url }}" alt="{{ store.name }}" height="32" style="height: 32px; width: auto; border: 0;" /></a></mj-text>
                              {% else %}
                                <mj-text font-size="22px" font-weight="700" color="{{ brand.heading_color }}" text-transform="uppercase"><a href="{{ store.url }}" style="color: {{ brand.heading_color }}; text-decoration: none;">{{ store.name }}</a></mj-text>
                              {% endif %}
                            </mj-column>
                          </mj-section>
                          {{ content_for_layout }}
                        </mj-wrapper>
                        <mj-section padding="64px 24px">
                          <mj-column>
                            <mj-text font-size="13px" line-height="1.5" css-class="footer"><a href="{{ store.url }}" style="font-weight: 500; text-decoration: none;">{{ store.name }}</a></mj-text>
                            {% if store.address != blank %}<mj-text mj-class="footer">{{ store.address }}</mj-text>{% endif %}
                            {% if store.support_email != blank %}<mj-text mj-class="footer" css-class="footer"><a href="mailto:{{ store.support_email }}">{{ store.support_email }}</a></mj-text>{% endif %}
                            <mj-text mj-class="footer" padding="20px 0 0">&copy; {{ 'now' | date: '%Y' }} {{ store.name }}</mj-text>
                          </mj-column>
                        </mj-section>
                      </mj-body>
                    </mjml>
                  language: any
                  customized_languages: []
                  kind: layout
                  customized: false
                  published_at:
                  default_subject:
                  default_body: |
                    {% assign brand = store.branding %}<mjml lang="{{ locale }}">
                      <mj-head>
                        <mj-title>{{ subject }}</mj-title>
                        {% if brand.font_url %}<mj-font name="{{ brand.font_family | split: ',' | first }}" href="{{ brand.font_url }}" />{% endif %}
                        <mj-attributes>
                          <mj-all font-family="{{ brand.font_family }}" />
                          <mj-section padding="0" />
                          <mj-column padding="0" />
                          <mj-text padding="0" color="{{ brand.text_color }}" font-size="14px" line-height="1.6" align="center" />
                          <mj-button background-color="{{ brand.button_color }}" border="{{ brand.button_border }}" border-radius="8px" color="{{ brand.button_text_color }}" font-size="15px" font-weight="500" line-height="1.6" inner-padding="12px 20px" padding="32px 0 0" />
                          <mj-table padding="0" color="{{ brand.text_color }}" font-size="14px" line-height="1.6" />
                          <mj-class name="heading" font-family="{{ brand.heading_font_family }}" font-size="40px" font-weight="700" line-height="1.2" letter-spacing="-0.8px" color="{{ brand.heading_color }}" css-class="heading" />
                          <mj-class name="greeting" padding="24px 0 0" font-size="15px" font-weight="500" color="{{ brand.heading_color }}" />
                          <mj-class name="lead" padding="12px 0 0" />
                          <mj-class name="note" padding="24px 0 0" font-size="13px" css-class="note" />
                          <mj-class name="section-heading" padding="48px 0 16px" font-family="{{ brand.heading_font_family }}" font-size="16px" font-weight="500" letter-spacing="-0.16px" align="left" />
                          <mj-class name="body" padding="16px 0 0" align="left" />
                          <mj-class name="footer" padding="12px 0 0" font-size="11px" line-height="1.5" />
                        </mj-attributes>
                        <mj-style>
                          {% if brand.font == 'inter' %}
                          @font-face { font-family: "Geist"; font-style: normal; font-weight: 500 700; src: url("https://fonts.gstatic.com/s/geist/v4/gyByhwUxId8gMEwcGFU.woff2") format("woff2"); }
                          @font-face { font-family: "Inter"; font-style: normal; font-weight: 400 450; src: url("https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuOKfMZg.ttf") format("truetype"); }
                          @font-face { font-family: "Inter"; font-style: normal; font-weight: 500; src: url("https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuI6fMZg.ttf") format("truetype"); }
                          @font-face { font-family: "Inter"; font-style: normal; font-weight: 600; src: url("https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuGKYMZg.ttf") format("truetype"); }
                          {% endif %}
                          a { color: {{ brand.link_color }}; }
                          .hero > table { max-width: 420px; margin: 0 auto; }
                          .note a { color: {{ brand.text_color }}; word-break: break-all; }
                          .footer a { color: {{ brand.text_color }}; }
                          .item { width: 100%; background-color: #F0F0F0; border-radius: 16px; margin: 0 0 8px; }
                          .item_image { padding: 8px; width: 96px; }
                          .item_thumb { display: block; width: 80px; height: auto; border-radius: 12px; }
                          .item_thumb_placeholder { width: 80px; height: 80px; background-color: #E4E4E4; border-radius: 12px; }
                          .item_info { padding: 8px 16px 8px 8px; }
                          .item_name { font-size: 15px; line-height: 1.5; font-weight: 500; color: {{ brand.heading_color }}; text-decoration: none; }
                          .item_meta { margin: 2px 0 0; font-size: 13px; line-height: 1.5; color: {{ brand.text_color }}; }
                          .item_amount { padding: 8px 16px 8px 8px; text-align: right; white-space: nowrap; }
                          .item_qty { margin: 0; font-size: 13px; line-height: 1.5; color: {{ brand.text_color }}; }
                          .item_price { margin: 2px 0 0; font-size: 15px; line-height: 1.5; font-weight: 500; color: {{ brand.heading_color }}; }
                          .summary td { padding: 6px 0; font-size: 14px; line-height: 1.6; color: {{ brand.text_color }}; }
                          .summary_value { font-size: 15px; font-weight: 500; text-align: right; white-space: nowrap; color: {{ brand.heading_color }}; }
                          .summary_sub { display: block; font-size: 13px; line-height: 1.5; }
                          .summary_total td { padding: 14px 0 0; border-top: 1px solid #E8E9E9; font-weight: 500; color: {{ brand.heading_color }}; }
                          .summary_total .summary_value { font-weight: 600; }
                          .mailer_hero h1 { margin: 0; font-family: {{ brand.heading_font_family }}; font-size: 40px; line-height: 1.2; letter-spacing: -0.8px; font-weight: 700; color: {{ brand.heading_color }}; }
                          .mailer_hero p { margin: 12px 0 0; }
                          .mailer_hero .greeting { margin-top: 24px; font-size: 15px; font-weight: 500; color: {{ brand.heading_color }}; }
                          .mailer_hero .sub { margin-top: 24px; font-size: 13px; }
                          @media only screen and (max-width: 600px) {
                            .heading div { font-size: 32px !important; letter-spacing: -0.64px !important; }
                          }
                        </mj-style>
                      </mj-head>
                      <mj-body background-color="{{ brand.background_color }}" width="640px">
                        <mj-wrapper background-color="{{ brand.card_color }}" padding="56px 24px">
                          <mj-section padding="0 0 32px">
                            <mj-column>
                              {% if store.logo_url and store.logo_width %}
                                <mj-image src="{{ store.logo_url }}" href="{{ store.url }}" alt="{{ store.name }}" width="{{ store.logo_width }}px" height="32px" padding="0" />
                              {% elsif store.logo_url %}
                                <mj-text><a href="{{ store.url }}"><img src="{{ store.logo_url }}" alt="{{ store.name }}" height="32" style="height: 32px; width: auto; border: 0;" /></a></mj-text>
                              {% else %}
                                <mj-text font-size="22px" font-weight="700" color="{{ brand.heading_color }}" text-transform="uppercase"><a href="{{ store.url }}" style="color: {{ brand.heading_color }}; text-decoration: none;">{{ store.name }}</a></mj-text>
                              {% endif %}
                            </mj-column>
                          </mj-section>
                          {{ content_for_layout }}
                        </mj-wrapper>
                        <mj-section padding="64px 24px">
                          <mj-column>
                            <mj-text font-size="13px" line-height="1.5" css-class="footer"><a href="{{ store.url }}" style="font-weight: 500; text-decoration: none;">{{ store.name }}</a></mj-text>
                            {% if store.address != blank %}<mj-text mj-class="footer">{{ store.address }}</mj-text>{% endif %}
                            {% if store.support_email != blank %}<mj-text mj-class="footer" css-class="footer"><a href="mailto:{{ store.support_email }}">{{ store.support_email }}</a></mj-text>{% endif %}
                            <mj-text mj-class="footer" padding="20px 0 0">&copy; {{ 'now' | date: '%Y' }} {{ store.name }}</mj-text>
                          </mj-column>
                        </mj-section>
                      </mj-body>
                    </mjml>
                  published_language:
                  default_changed: false
                  base_subject:
                  base_body:
                  draft:
                meta: {}
  "/api/v3/admin/email_templates/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: The template key with dots, e.g. `spree.order_mailer.confirm_email`
      schema:
        type: string
    get:
      summary: Get an email template
      tags:
      - Email Templates
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the template for one language: what customers receive now,
        Spree's default, and the draft with its `lock_version`. When Spree's
        default changed since the store's version started from it,
        `default_changed` is true and `base_body` holds the default it
        started from, to compare with `default_body`.


        **Required scope:** `read_email_templates` (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 template = await client.emailTemplates.get('spree.order_mailer.confirm_email', {
            language: 'de',
            expand: ['draft.updated_by'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /email_templates/{id} -d '{"language":"de","expand":["draft.updated_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: language
        in: query
        required: false
        description: A language code, or `any` (the default)
        schema:
          type: string
      - name: expand
        in: query
        required: false
        description: Comma-separated associations to expand (`draft.updated_by`)
        schema:
          type: string
      responses:
        '200':
          description: email template found
          content:
            application/json:
              example:
                id: spree.order_mailer.confirm_email
                key: spree/order_mailer/confirm_email
                subject: Order {{ order.number }} confirmed
                body: "<mj-section><mj-column><mj-text>Thanks for your order, {{ order.customer_name
                  }}!</mj-text></mj-column></mj-section>\n"
                language: any
                customized_languages: []
                kind: email
                customized: false
                published_at:
                default_subject: Order {{ order.number }} confirmed
                default_body: "<mj-section><mj-column><mj-text>Thanks for your order,
                  {{ order.customer_name }}!</mj-text></mj-column></mj-section>\n"
                published_language:
                default_changed: true
                base_subject: Reset {{ store.name }}
                base_body: "<mj-section><mj-column><mj-text>Default</mj-text></mj-column></mj-section>"
                draft:
                  id: etdr_UkLWZg9DAJ
                  subject: Reset {{ store.name }}
                  body: "<mj-section><mj-column><mj-text>Thanks, {{ order.customer_name
                    }}!</mj-text></mj-column></mj-section>"
                  lock_version: 0
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  updated_by_id: adm_UkLWZg9DAJ
                  updated_by_type: admin_user
              schema:
                "$ref": "#/components/schemas/EmailTemplate"
        '404':
          description: not an editable template
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: record not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    delete:
      summary: Revert an email template to Spree's default
      tags:
      - Email Templates
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Goes back to Spree's default for one language and discards the draft.
        The store's published versions are kept, so one can still be restored.


        **Required scope:** `write_email_templates` (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',
          })

          // Goes back to Spree's default. Published versions stay in the history.
          const template = await client.emailTemplates.revert('spree.order_mailer.confirm_email')
      - lang: bash
        label: Spree CLI
        source: spree api delete /email_templates/{id}
      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: language
        in: query
        required: false
        description: A language code, or `any` (the default)
        schema:
          type: string
      - name: lock_version
        in: query
        required: false
        description: The draft's `lock_version` as last seen; a draft saved since
          is refused with 409
        schema:
          type: integer
      responses:
        '200':
          description: email template reverted
          content:
            application/json:
              example:
                id: spree.order_mailer.confirm_email
                key: spree/order_mailer/confirm_email
                subject: Order {{ order.number }} confirmed
                body: "<mj-section><mj-column><mj-text>Thanks for your order, {{ order.customer_name
                  }}!</mj-text></mj-column></mj-section>\n"
                language: any
                customized_languages: []
                kind: email
                customized: false
                published_at:
                default_subject: Order {{ order.number }} confirmed
                default_body: "<mj-section><mj-column><mj-text>Thanks for your order,
                  {{ order.customer_name }}!</mj-text></mj-column></mj-section>\n"
                published_language:
                default_changed: false
                base_subject:
                base_body:
                draft:
              schema:
                "$ref": "#/components/schemas/EmailTemplate"
  "/api/v3/admin/email_templates/{email_template_id}/draft":
    parameters:
    - name: email_template_id
      in: path
      required: true
      description: The template key with dots
      schema:
        type: string
    put:
      summary: Save an email template draft
      tags:
      - Email Templates
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Saves the draft, in any state; customers keep receiving the published
        version until it is published. Send the `lock_version` the draft was
        loaded with: a save made from an older copy is refused with 409,
        naming who saved last. The first save starts from what is published,
        else Spree's default.


        **Required scope:** `write_email_templates` (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 the lock_version the draft was loaded with: a save made from an
          // older copy is refused with 409, naming who saved last.
          const template = await client.emailTemplates.draft.update('spree.order_mailer.confirm_email', {
            subject: 'Your order {{ order.number }} is confirmed',
            body: '<mj-section><mj-column><mj-text>Thanks, {{ order.customer_name }}!</mj-text></mj-column></mj-section>',
            lock_version: 0,
          })
      - lang: bash
        label: Spree CLI
        source: spree api put /email_templates/{email_template_id}/draft -d '{"subject":"Your
          order {{ order.number }} is confirmed","body":"<mj-section><mj-column><mj-text>Thanks,
          {{ order.customer_name }}!</mj-text></mj-column></mj-section>","lock_version":0}'
      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: draft saved
          content:
            application/json:
              example:
                id: spree.order_mailer.confirm_email
                key: spree/order_mailer/confirm_email
                subject: Order {{ order.number }} confirmed
                body: "<mj-section><mj-column><mj-text>Thanks for your order, {{ order.customer_name
                  }}!</mj-text></mj-column></mj-section>\n"
                language: any
                customized_languages: []
                kind: email
                customized: false
                published_at:
                default_subject: Order {{ order.number }} confirmed
                default_body: "<mj-section><mj-column><mj-text>Thanks for your order,
                  {{ order.customer_name }}!</mj-text></mj-column></mj-section>\n"
                published_language:
                default_changed: false
                base_subject:
                base_body:
                draft:
                  id: etdr_UkLWZg9DAJ
                  subject: Your order {{ order.number }} is confirmed
                  body: "<mj-section><mj-column><mj-text>Thanks, {{ order.customer_name
                    }}!</mj-text></mj-column></mj-section>"
                  lock_version: 0
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  updated_by_id: adm_UkLWZg9DAJ
                  updated_by_type: admin_user
              schema:
                "$ref": "#/components/schemas/EmailTemplate"
        '409':
          description: saved by someone else since it was loaded
          content:
            application/json:
              example:
                error:
                  code: email_template_stale
                  message: Mirta Hamill saved this draft after you opened it. Reload
                    to see their changes before saving yours.
                  details:
                    updated_by: Mirta Hamill
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/EmailTemplateDraftParams"
        required: true
    delete:
      summary: Discard an email template draft
      tags:
      - Email Templates
      security:
      - api_key: []
        bearer_auth: []
      description: "**Required scope:** `write_email_templates` (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 template = await client.emailTemplates.draft.delete('spree.order_mailer.confirm_email')
      - lang: bash
        label: Spree CLI
        source: spree api delete /email_templates/{email_template_id}/draft
      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: language
        in: query
        required: false
        description: A language code, or `any` (the default)
        schema:
          type: string
      - name: lock_version
        in: query
        required: false
        description: The draft's `lock_version` as last seen; a draft saved since
          is refused with 409
        schema:
          type: integer
      responses:
        '200':
          description: draft discarded
          content:
            application/json:
              example:
                id: spree.order_mailer.confirm_email
                key: spree/order_mailer/confirm_email
                subject: Order {{ order.number }} confirmed
                body: "<mj-section><mj-column><mj-text>Thanks for your order, {{ order.customer_name
                  }}!</mj-text></mj-column></mj-section>\n"
                language: any
                customized_languages: []
                kind: email
                customized: false
                published_at:
                default_subject: Order {{ order.number }} confirmed
                default_body: "<mj-section><mj-column><mj-text>Thanks for your order,
                  {{ order.customer_name }}!</mj-text></mj-column></mj-section>\n"
                published_language:
                default_changed: false
                base_subject:
                base_body:
                draft:
              schema:
                "$ref": "#/components/schemas/EmailTemplate"
  "/api/v3/admin/email_templates/{email_template_id}/publication":
    parameters:
    - name: email_template_id
      in: path
      required: true
      description: The template key with dots
      schema:
        type: string
    post:
      summary: Publish an email template draft
      tags:
      - Email Templates
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Makes the draft what customers receive. The draft is first rendered
        with sample data; one that does not render (for the layout or a
        partial: in any email using it) is refused with 422, listing each
        problem with its email and line.


        **Required scope:** `write_email_templates` (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',
          })

          // Refused with 422 and each problem's email and line when the draft does not render.
          const template = await client.emailTemplates.publish('spree.order_mailer.confirm_email')
      - lang: bash
        label: Spree CLI
        source: spree api post /email_templates/{email_template_id}/publication -d
          '{ ... }'
      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: draft published
          content:
            application/json:
              example:
                id: spree.order_mailer.confirm_email
                key: spree/order_mailer/confirm_email
                subject: Reset {{ store.name }}
                body: "<mj-section><mj-column><mj-text>Thanks, {{ order.customer_name
                  }}!</mj-text></mj-column></mj-section>"
                language: any
                customized_languages:
                - any
                kind: email
                customized: true
                published_at: '2026-01-15T12:00:00Z'
                default_subject: Order {{ order.number }} confirmed
                default_body: "<mj-section><mj-column><mj-text>Thanks for your order,
                  {{ order.customer_name }}!</mj-text></mj-column></mj-section>\n"
                published_language: any
                default_changed: true
                base_subject: Reset {{ store.name }}
                base_body: "<mj-section><mj-column><mj-text>Default</mj-text></mj-column></mj-section>"
                draft:
              schema:
                "$ref": "#/components/schemas/EmailTemplate"
        '422':
          description: the draft does not render
          content:
            application/json:
              example:
                error:
                  code: email_template_invalid
                  message: 'Liquid error (line 1): undefined variable nubmer'
                  details:
                    problems:
                    - email: spree.order_mailer.confirm_email
                      locale: any
                      message: 'Liquid error (line 1): undefined variable nubmer'
                      line: 1
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/EmailTemplateVersionParams"
  "/api/v3/admin/email_templates/{email_template_id}/preview":
    parameters:
    - name: email_template_id
      in: path
      required: true
      description: The template key with dots
      schema:
        type: string
    post:
      summary: Preview an email template
      tags:
      - Email Templates
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Renders the template with sample data built from the store's latest
        matching record, or the one `record_id` names, and returns the email
        with the variables it was rendered with. An unsaved `subject` and
        `body` take the place of the current version. The layout and partials
        render inside an email, `email_key` or the first one. `branding`
        previews colors and a font before they are saved to the store.


        **Required scope:** `write_email_templates` (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 preview = await client.emailTemplates.preview('spree.order_mailer.confirm_email', {
            body: '<mj-section><mj-column><mj-text>Thanks, {{ order.customer_name }}!</mj-text></mj-column></mj-section>',
            record_id: 'or_m3Rp9wXz',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /email_templates/{email_template_id}/preview -d '{"body":"<mj-section><mj-column><mj-text>Thanks,
          {{ order.customer_name }}!</mj-text></mj-column></mj-section>","record_id":"or_m3Rp9wXz"}'
      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: email template rendered
          content:
            application/json:
              example:
                id:
                subject: Order R123456789 confirmed
                html: "<!doctype html><html lang=\"en\" dir=\"auto\" xmlns=\"http://www.w3.org/1999/xhtml\"
                  xmlns:v=\"urn:schemas-microsoft-com:vml\" xmlns:o=\"urn:schemas-microsoft-com:office:office\"><head><title>Order
                  R123456789 confirmed</title><!--[if !mso]><!--><meta http-equiv=\"X-UA-Compatible\"
                  content=\"IE=edge\"><!--<![endif]--><meta http-equiv=\"Content-Type\"
                  content=\"text/html; charset=UTF-8\"><meta name=\"viewport\" content=\"width=device-width,
                  initial-scale=1\">\n<style type=\"text/css\">\n#outlook a { padding:
                  0; }\nbody { margin: 0; padding: 0; -webkit-text-size-adjust: 100%;
                  -ms-text-size-adjust: 100%; }\ntable, td { border-collapse: collapse;
                  mso-table-lspace: 0pt; mso-table-rspace: 0pt; }\nimg { border: 0;
                  height: auto; line-height: 100%; outline: none; text-decoration:
                  none; -ms-interpolation-mode: bicubic; }\np { display: block; margin:
                  13px 0; }\n</style>\n<!--[if mso]>\n<noscript>\n<xml>\n<o:OfficeDocumentSettings>\n
                  \ <o:AllowPNG/>\n  <o:PixelsPerInch>96</o:PixelsPerInch>\n</o:OfficeDocumentSettings>\n</xml>\n</noscript>\n<![endif]-->\n<!--[if
                  lte mso 11]>\n<style type=\"text/css\">\n.mj-outlook-group-fix {
                  width:100% !important; }\n</style>\n<![endif]-->\n<style type=\"text/css\">@media
                  only screen and (min-width:480px) { .mj-column-per-100 { width:100%
                  !important; max-width:100%; }  }</style><style media=\"screen and
                  (min-width:480px)\">.moz-text-html .mj-column-per-100 { width:100%
                  !important; max-width:100%; } </style><style type=\"text/css\">@font-face
                  { font-family: \"Geist\"; font-style: normal; font-weight: 500 700;
                  src: url(\"https://fonts.gstatic.com/s/geist/v4/gyByhwUxId8gMEwcGFU.woff2\")
                  format(\"woff2\"); }\n      @font-face { font-family: \"Inter\";
                  font-style: normal; font-weight: 400 450; src: url(\"https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuOKfMZg.ttf\")
                  format(\"truetype\"); }\n      @font-face { font-family: \"Inter\";
                  font-style: normal; font-weight: 500; src: url(\"https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuI6fMZg.ttf\")
                  format(\"truetype\"); }\n      @font-face { font-family: \"Inter\";
                  font-style: normal; font-weight: 600; src: url(\"https://fonts.gstatic.com/s/inter/v20/UcCO3FwrK3iLTeHuS_nVMrMxCp50SjIw2boKoduKmMEVuGKYMZg.ttf\")
                  format(\"truetype\"); }\n      \n      a { color: #332C2C; }\n      .hero
                  > table { max-width: 420px; margin: 0 auto; }\n      .note a { color:
                  #726A6A; word-break: break-all; }\n      .footer a { color: #726A6A;
                  }\n      .item { width: 100%; background-color: #F0F0F0; border-radius:
                  16px; margin: 0 0 8px; }\n      .item_image { padding: 8px; width:
                  96px; }\n      .item_thumb { display: block; width: 80px; height:
                  auto; border-radius: 12px; }\n      .item_thumb_placeholder { width:
                  80px; height: 80px; background-color: #E4E4E4; border-radius: 12px;
                  }\n      .item_info { padding: 8px 16px 8px 8px; }\n      .item_name
                  { font-size: 15px; line-height: 1.5; font-weight: 500; color: #332C2C;
                  text-decoration: none; }\n      .item_meta { margin: 2px 0 0; font-size:
                  13px; line-height: 1.5; color: #726A6A; }\n      .item_amount {
                  padding: 8px 16px 8px 8px; text-align: right; white-space: nowrap;
                  }\n      .item_qty { margin: 0; font-size: 13px; line-height: 1.5;
                  color: #726A6A; }\n      .item_price { margin: 2px 0 0; font-size:
                  15px; line-height: 1.5; font-weight: 500; color: #332C2C; }\n      .summary
                  td { padding: 6px 0; font-size: 14px; line-height: 1.6; color: #726A6A;
                  }\n      .summary_value { font-size: 15px; font-weight: 500; text-align:
                  right; white-space: nowrap; color: #332C2C; }\n      .summary_sub
                  { display: block; font-size: 13px; line-height: 1.5; }\n      .summary_total
                  td { padding: 14px 0 0; border-top: 1px solid #E8E9E9; font-weight:
                  500; color: #332C2C; }\n      .summary_total .summary_value { font-weight:
                  600; }\n      .mailer_hero h1 { margin: 0; font-family: Geist, Inter,
                  Helvetica, Arial, sans-serif; font-size: 40px; line-height: 1.2;
                  letter-spacing: -0.8px; font-weight: 700; color: #332C2C; }\n      .mailer_hero
                  p { margin: 12px 0 0; }\n      .mailer_hero .greeting { margin-top:
                  24px; font-size: 15px; font-weight: 500; color: #332C2C; }\n      .mailer_hero
                  .sub { margin-top: 24px; font-size: 13px; }\n      @media only screen
                  and (max-width: 600px) {\n        .heading div { font-size: 32px
                  !important; letter-spacing: -0.64px !important; }\n      }</style></head><body
                  style=\"word-spacing:normal;background-color:#FFFFFF;\"><div lang=\"en\"
                  dir=\"auto\" style=\"background-color:#FFFFFF;\"><!--[if mso | IE]><table
                  border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\"
                  bgcolor=\"#F6F6F6\" align=\"center\" width=\"640\" style=\"width:640px;\"><tr><td
                  style=\"line-height:0px;font-size:0px;mso-line-height-rule:exactly;\"><![endif]--><div
                  style=\"background:#F6F6F6;background-color:#F6F6F6;margin:0px auto;max-width:640px;\"><table
                  border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\"
                  align=\"center\" style=\"background:#F6F6F6;background-color:#F6F6F6;width:100%;\"><tbody><tr><td
                  style=\"direction:ltr;font-size:0px;padding:56px 24px;text-align:center;\"><!--[if
                  mso | IE]><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"
                  role=\"presentation\"><tr><td width=\"640px\"><![endif]--><!--[if
                  mso | IE]><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"
                  role=\"presentation\" align=\"center\" width=\"592\" style=\"width:592px;\"><tr><td
                  style=\"line-height:0px;font-size:0px;mso-line-height-rule:exactly;\"><![endif]--><div
                  style=\"margin:0px auto;max-width:592px;\"><table border=\"0\" cellpadding=\"0\"
                  cellspacing=\"0\" role=\"presentation\" align=\"center\" style=\"width:100%;\"><tbody><tr><td
                  style=\"direction:ltr;font-size:0px;padding:0 0 32px;text-align:center;\"><!--[if
                  mso | IE]><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"
                  role=\"presentation\"><tr><![endif]--><!--[if mso | IE]><td style=\"vertical-align:top;width:592px;\"><![endif]--><div
                  class=\"mj-outlook-group-fix mj-column-per-100\" style=\"font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;\"><table
                  border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\"
                  width=\"100%\"><tbody><tr><td style=\"vertical-align:top;padding:0;\"><table
                  border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\"
                  width=\"100%\"><tbody><tr><td align=\"center\" style=\"font-size:0px;padding:0;word-break:break-word;\"><div
                  style=\"font-family:Inter, Helvetica, Arial, sans-serif;font-size:22px;font-weight:700;line-height:1.6;text-align:center;text-transform:uppercase;color:#332C2C;\"><a
                  href=\"http://www.example.com:3000\" style=\"color: #332C2C; text-decoration:
                  none;\">Spree Test Store</a></div></td></tr></tbody></table></td></tr></tbody></table></div><!--[if
                  mso | IE]></td><![endif]--><!--[if mso | IE]></tr></table><![endif]--></td></tr></tbody></table></div><!--[if
                  mso | IE]></td></tr></table><![endif]--><!--[if mso | IE]></td></tr><tr><td
                  width=\"640px\"><![endif]--><!--[if mso | IE]><table border=\"0\"
                  cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\" align=\"center\"
                  width=\"592\" style=\"width:592px;\"><tr><td style=\"line-height:0px;font-size:0px;mso-line-height-rule:exactly;\"><![endif]--><div
                  style=\"margin:0px auto;max-width:592px;\"><table border=\"0\" cellpadding=\"0\"
                  cellspacing=\"0\" role=\"presentation\" align=\"center\" style=\"width:100%;\"><tbody><tr><td
                  style=\"direction:ltr;font-size:0px;padding:0;text-align:center;\"><!--[if
                  mso | IE]><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"
                  role=\"presentation\"><tr><![endif]--><!--[if mso | IE]><td style=\"vertical-align:top;width:592px;\"><![endif]--><div
                  class=\"mj-outlook-group-fix mj-column-per-100\" style=\"font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;\"><table
                  border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\"
                  width=\"100%\"><tbody><tr><td style=\"vertical-align:top;padding:0;\"><table
                  border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\"
                  width=\"100%\"><tbody><tr><td align=\"center\" style=\"font-size:0px;padding:0;word-break:break-word;\"><div
                  style=\"font-family:Inter, Helvetica, Arial, sans-serif;font-size:14px;line-height:1.6;text-align:center;color:#726A6A;\">Thanks,
                  Ann Lee!</div></td></tr></tbody></table></td></tr></tbody></table></div><!--[if
                  mso | IE]></td><![endif]--><!--[if mso | IE]></tr></table><![endif]--></td></tr></tbody></table></div><!--[if
                  mso | IE]></td></tr></table><![endif]--><!--[if mso | IE]></td></tr></table><![endif]--></td></tr></tbody></table></div><!--[if
                  mso | IE]></td></tr></table><![endif]--><!--[if mso | IE]><table
                  border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\"
                  align=\"center\" width=\"640\" style=\"width:640px;\"><tr><td style=\"line-height:0px;font-size:0px;mso-line-height-rule:exactly;\"><![endif]--><div
                  style=\"margin:0px auto;max-width:640px;\"><table border=\"0\" cellpadding=\"0\"
                  cellspacing=\"0\" role=\"presentation\" align=\"center\" style=\"width:100%;\"><tbody><tr><td
                  style=\"direction:ltr;font-size:0px;padding:64px 24px;text-align:center;\"><!--[if
                  mso | IE]><table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"
                  role=\"presentation\"><tr><![endif]--><!--[if mso | IE]><td style=\"vertical-align:top;width:640px;\"><![endif]--><div
                  class=\"mj-outlook-group-fix mj-column-per-100\" style=\"font-size:0px;text-align:left;direction:ltr;display:inline-block;vertical-align:top;width:100%;\"><table
                  border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\"
                  width=\"100%\"><tbody><tr><td style=\"vertical-align:top;padding:0;\"><table
                  border=\"0\" cellpadding=\"0\" cellspacing=\"0\" role=\"presentation\"
                  width=\"100%\"><tbody><tr><td align=\"center\" class=\"footer\"
                  style=\"font-size:0px;padding:0;word-break:break-word;\"><div style=\"font-family:Inter,
                  Helvetica, Arial, sans-serif;font-size:13px;line-height:1.5;text-align:center;color:#726A6A;\"><a
                  href=\"http://www.example.com:3000\" style=\"font-weight: 500; text-decoration:
                  none;\">Spree Test Store</a></div></td></tr><tr><td align=\"center\"
                  class=\"footer\" style=\"font-size:0px;padding:12px 0 0;word-break:break-word;\"><div
                  style=\"font-family:Inter, Helvetica, Arial, sans-serif;font-size:11px;line-height:1.5;text-align:center;color:#726A6A;\"><a
                  href=\"mailto:support@example.com\">support@example.com</a></div></td></tr><tr><td
                  align=\"center\" style=\"font-size:0px;padding:20px 0 0;word-break:break-word;\"><div
                  style=\"font-family:Inter, Helvetica, Arial, sans-serif;font-size:11px;line-height:1.5;text-align:center;color:#726A6A;\">&copy;
                  2026 Spree Test Store</div></td></tr></tbody></table></td></tr></tbody></table></div><!--[if
                  mso | IE]></td><![endif]--><!--[if mso | IE]></tr></table><![endif]--></td></tr></tbody></table></div><!--[if
                  mso | IE]></td></tr></table><![endif]--></div></body></html>"
                text: |
                  Spree Test Store (http://www.example.com:3000)

                  Thanks, Ann Lee!

                  Spree Test Store (http://www.example.com:3000)

                  support@example.com

                  © 2026 Spree Test Store
                email_key: spree.order_mailer.confirm_email
                variables:
                  store:
                    id: store_UkLWZg9DAJ
                    name: Spree Test Store
                    address:
                    mail_from_address: no-reply@example.com
                    default_currency: USD
                    default_locale: en
                    url: http://www.example.com:3000
                    support_email: support@example.com
                    logo_url:
                    logo_width:
                    branding:
                      background_color: "#FFFFFF"
                      card_color: "#F6F6F6"
                      text_color: "#726A6A"
                      heading_color: "#332C2C"
                      accent_color:
                      link_color: "#332C2C"
                      button_color: "#FFFFFF"
                      button_text_color: "#1F2222"
                      button_border: '1px solid #E8E9E9'
                      font: inter
                      font_family: Inter, Helvetica, Arial, sans-serif
                      heading_font_family: Geist, Inter, Helvetica, Arial, sans-serif
                      font_url:
                  locale: en
                  user:
                    first_name: Ann
                    email: ann@example.com
                  order:
                    number: R123456789
                    customer_name: Ann Lee
                  reset_url: http://www.example.com:3000/reset-password?token=preview
              schema:
                "$ref": "#/components/schemas/EmailTemplatePreview"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/EmailTemplatePreviewParams"
        required: true
  "/api/v3/admin/email_templates/{email_template_id}/test_email":
    parameters:
    - name: email_template_id
      in: path
      required: true
      description: The template key with dots
      schema:
        type: string
    post:
      summary: Send a test email
      tags:
      - Email Templates
      security:
      - bearer_auth: []
      description: |
        Sends the template, rendered as the preview renders it, to the
        signed-in admin, and never to another address: the sample data comes
        from a real customer's records. Takes the same body as the preview.
      x-codeSamples:
      - lang: javascript
        label: Spree Admin SDK
        source: |-
          import { createAdminClient } from '@spree/admin-sdk'

          const client = createAdminClient({
            baseUrl: 'https://your-store.com',
            jwtToken: 'eyJhbGciOi...',
          })

          // Sent to the signed-in admin, so this needs a client created with `jwtToken`;
          // a secret key has no inbox and is refused.
          const { sent_to } = await client.emailTemplates.sendTest('spree.order_mailer.confirm_email', {
            body: '<mj-section><mj-column><mj-text>Thanks, {{ order.customer_name }}!</mj-text></mj-column></mj-section>',
          })
      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:
        '202':
          description: test email queued
          content:
            application/json:
              example:
                sent_to: luba@oberbrunner.com
              schema:
                type: object
                properties:
                  sent_to:
                    type: string
                required:
                - sent_to
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/EmailTemplatePreviewParams"
        required: true
  "/api/v3/admin/email_templates/{email_template_id}/sample_records":
    parameters:
    - name: email_template_id
      in: path
      required: true
      description: The template key with dots
      schema:
        type: string
    get:
      summary: List records to preview an email template with
      tags:
      - Email Templates
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The store's five latest records the template can be previewed with,
        newest first, to pass as `record_id` to the preview. For the layout
        and partials, those of the email `email_key` names. Empty for an
        email that needs no record.


        **Required scope:** `write_email_templates` (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',
          })

          // The latest orders to preview the order confirmation with; pass one's id as `record_id`.
          const { data: records } = await client.emailTemplates.sampleRecords.list(
            'spree.order_mailer.confirm_email',
          )
      - lang: bash
        label: Spree CLI
        source: spree api get /email_templates/{email_template_id}/sample_records
      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: email_key
        in: query
        required: false
        description: For the layout or a partial, the email to show it in
        schema:
          type: string
      responses:
        '200':
          description: records found
          content:
            application/json:
              example:
                data:
                - id: or_UkLWZg9DAJ
                  label: R1001
                  created_at: '2026-01-15T12:00:00.000Z'
  "/api/v3/admin/email_templates/{email_template_id}/revisions":
    parameters:
    - name: email_template_id
      in: path
      required: true
      description: The template key with dots
      schema:
        type: string
    get:
      summary: List email template revisions
      tags:
      - Email Templates
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Every version of the template published in one language, newest
        first. Reverting to Spree's default keeps them.


        **Required scope:** `read_email_templates` (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 revisions = await client.emailTemplates.revisions.list('spree.order_mailer.confirm_email', {
            expand: ['published_by'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /email_templates/{email_template_id}/revisions -d '{"expand":["published_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: language
        in: query
        required: false
        description: A language code, or `any` (the default)
        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 (`published_by`)
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |

          **Sort by:** `created_at`, `id`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: EmailTemplateRevision
        sortable:
        - created_at
        - id
      responses:
        '200':
          description: revisions found
          content:
            application/json:
              example:
                data:
                - id: etrv_UkLWZg9DAJ
                  subject: Reset {{ store.name }}
                  body: "<mj-section><mj-column><mj-text>Hello</mj-text></mj-column></mj-section>"
                  created_at: '2026-01-15T12:00:00.000Z'
                  published_by_id: adm_UkLWZg9DAJ
                  published_by_type: admin_user
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
  "/api/v3/admin/email_templates/{email_template_id}/revisions/{revision_id}/restoration":
    parameters:
    - name: email_template_id
      in: path
      required: true
      description: The template key with dots
      schema:
        type: string
    - name: revision_id
      in: path
      required: true
      schema:
        type: string
    post:
      summary: Restore an email template revision
      tags:
      - Email Templates
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Copies the revision into the draft, to be published like any change.
        Send the draft's `lock_version` when one is open, as when saving it.


        **Required scope:** `write_email_templates` (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',
          })

          // Copies the revision into the draft, to publish like any change.
          const template = await client.emailTemplates.revisions.restore(
            'spree.order_mailer.confirm_email',
            'etrv_k5nR8xLq',
          )
      - lang: bash
        label: Spree CLI
        source: spree api post /email_templates/{email_template_id}/revisions/{revision_id}/restoration
          -d '{ ... }'
      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: revision copied into the draft
          content:
            application/json:
              example:
                id: spree.order_mailer.confirm_email
                key: spree/order_mailer/confirm_email
                subject: Reset {{ store.name }}
                body: "<mj-section><mj-column><mj-text>Hello</mj-text></mj-column></mj-section>"
                language: any
                customized_languages:
                - any
                kind: email
                customized: true
                published_at: '2026-01-15T12:00:00Z'
                default_subject: Order {{ order.number }} confirmed
                default_body: "<mj-section><mj-column><mj-text>Thanks for your order,
                  {{ order.customer_name }}!</mj-text></mj-column></mj-section>\n"
                published_language: any
                default_changed: true
                base_subject: Reset {{ store.name }}
                base_body: "<mj-section><mj-column><mj-text>Default</mj-text></mj-column></mj-section>"
                draft:
                  id: etdr_UkLWZg9DAJ
                  subject: Reset {{ store.name }}
                  body: "<mj-section><mj-column><mj-text>Thanks, {{ order.customer_name
                    }}!</mj-text></mj-column></mj-section>"
                  lock_version: 0
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  updated_by_id: adm_UkLWZg9DAJ
                  updated_by_type: admin_user
              schema:
                "$ref": "#/components/schemas/EmailTemplate"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/EmailTemplateRestoreParams"
  "/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()
      - lang: bash
        label: Spree CLI
        source: spree api get /exports
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `format` | One of `csv` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `seller_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `type` | Type | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[seller_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |

          </Accordion>

          **Sort by:** `created_at`, `format`, `id`, `number`, `seller_id`, `type`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Export
        sortable:
        - created_at
        - format
        - id
        - number
        - seller_id
        - type
        - updated_at
      responses:
        '200':
          description: exports found
          content:
            application/json:
              example:
                data:
                - id: exp_UkLWZg9DAJ
                  number: EF1001
                  format: csv
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  type: products
                  user_id: adm_UkLWZg9DAJ
                  done: false
                  store_id: store_UkLWZg9DAJ
                  seller_id:
                  seller_name:
                  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: 'products',
            search_params: { name_cont: 'shirt' },
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /exports -d '{"type":"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: EF1002
                format: csv
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: products
                user_id: adm_UkLWZg9DAJ
                done: false
                store_id: store_UkLWZg9DAJ
                seller_id:
                seller_name:
                filename:
                byte_size:
                download_url:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ExportCreateParams"
        required: 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')
      - lang: bash
        label: Spree CLI
        source: spree api get /exports/{id}
      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: EF1001
                format: csv
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: products
                user_id: adm_UkLWZg9DAJ
                done: false
                store_id: store_UkLWZg9DAJ
                seller_id:
                seller_name:
                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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /exports/{id}
      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)
      - lang: bash
        label: Spree CLI
        source: spree api get /exports/{id}/download
      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:
            text/csv:
              schema:
                type: string
                format: binary
  "/api/v3/admin/files":
    post:
      summary: Upload a file
      tags:
      - Files
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Accepts a file and returns a `signed_id` to send to the endpoint that
        uses it — `signed_id` on product media, `avatar_signed_id` on a
        customer, `attachment_signed_id` on an import, and so on.

        Two ways to send the bytes, one response:

        - **Presigned** (JSON): send the file's metadata, then `PUT` the bytes
          to `upload.url` with exactly `upload.headers`. Use this for anything
          large — the bytes go straight to storage.
        - **Multipart**: send the bytes in a `file` part. The file is stored
          before the response, so `upload` is null. Limited to 10 MB by default.

        `signed_id` is opaque: pass it back unchanged and never parse it. It
        stops being attachable at `expires_at`, one day after the upload.

        `visibility` picks the storage: `public` (the default) for images and
        videos customers see, `private` for documents, imports and digital
        products. Public uploads accept web images, videos and CSV; private
        uploads accept any type. `checksum` is the file's MD5 digest,
        base64-encoded — the storage service verifies the bytes against it.


        **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',
          })

          // Returns where to send the bytes: send the file to `upload.url` with
          // `upload.method` and `upload.headers`, then pass `signed_id` to the
          // endpoint that uses it.
          // `client.files.upload(file)` does both steps for you.
          const { signed_id, upload } = await client.files.create({
            filename: 'products.csv',
            content_type: 'text/csv',
            byte_size: 48213,
            checksum: 'XrY7u+Ae7tCTyyK7j1rNww==',
            visibility: 'private',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /files -d '{"filename":"products.csv","content_type":"text/csv","byte_size":48213,"checksum":"XrY7u+Ae7tCTyyK7j1rNww==","visibility":"private"}'
      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: presigned upload target created
          content:
            application/json:
              example:
                signed_id: eyJfcmFpbHMiOnsiZGF0YSI6MSwiZXhwIjoiMjAyNi0wMS0xNlQxMjowMDowMC4wMDBaIiwicHVyIjoiYmxvYl9pZCJ9fQ==--5cf7f6bc12adaf5ef31072ed4b5eb4c1732ca992
                filename: products.csv
                content_type: text/csv
                byte_size: 48213
                visibility: private
                expires_at: '2026-01-16T12:00:00.000Z'
                upload:
                  method: PUT
                  url: http://www.example.com/rails/active_storage/disk/eyJfcmFpbHMiOnsiZGF0YSI6eyJrZXkiOiJxcmZsMnNod3YwYmR4cWF3ZWFocDZvYjhlYzh5IiwiY29udGVudF90eXBlIjoidGV4dC9jc3YiLCJjb250ZW50X2xlbmd0aCI6NDgyMTMsImNoZWNrc3VtIjoiaGdKTXJSNkRFQjJYTloxelVRVVJWZz09Iiwic2VydmljZV9uYW1lIjoidGVzdCJ9LCJleHAiOiIyMDI2LTAxLTE1VDEyOjA1OjAwLjAwMFoiLCJwdXIiOiJibG9iX3Rva2VuIn19--58771025051fac3b85fe97de3d0af5379be8ff83
                  headers:
                    Content-Type: text/csv
              schema:
                "$ref": "#/components/schemas/FileUpload"
        '422':
          description: content type not allowed for a public upload
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Content type is not included in the list
                  details:
                    content_type:
                    - value: application/x-sh
                      code: inclusion
                      message: is not included in the list
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/FileUploadCreateParams"
          multipart/form-data:
            schema:
              "$ref": "#/components/schemas/FileUploadCreateParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/fulfillments
      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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `number`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Fulfillment
        sortable:
        - created_at
        - id
        - number
        - updated_at
      responses:
        '200':
          description: fulfillments found
          content:
            application/json:
              example:
                data:
                - id: ful_UkLWZg9DAJ
                  number: R1001-F1
                  tracking: U10000
                  tracking_url:
                  pickup_point_data:
                  selected_delivery_rate_id: dr_gbHJdmfrXB
                  unpriced: false
                  cost: '100.00'
                  total: '100.00'
                  discount_total: '0.00'
                  additional_tax_total: '0.00'
                  included_tax_total: '0.00'
                  tax_total: '0.00'
                  status: unfulfilled
                  fulfillment_type: shipping
                  fulfilled_at:
                  delivered_at:
                  items:
                  - item_id: li_UkLWZg9DAJ
                    variant_id: variant_UkLWZg9DAJ
                    quantity: 1
                  deliveries:
                  - id: dlv_UkLWZg9DAJ
                    tracking_number: U10000
                    carrier:
                    carrier_name:
                    service:
                    status: pending
                    tracking_url:
                    estimated_delivery_at:
                    delivered_at:
                    details:
                    created_at: '2026-01-15T12:00:00.000Z'
                    updated_at: '2026-01-15T12:00:00.000Z'
                    shipping_label_id:
                  external_references: {}
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  adjustment_total: '0.00'
                  pre_tax_amount: '100.00'
                  order_id: or_UkLWZg9DAJ
                  stock_location_id: sloc_UkLWZg9DAJ
                  documents: []
                  labels: []
                  provider_generates_labels: false
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Create a fulfillment
      tags:
      - Fulfillments
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Manually creates a fulfillment on a completed order, bypassing order routing — for example to mirror a shipment handled by an external carrier or 3PL. Moves the requested line item quantities out of their current fulfillments; when `items` is omitted, every not-yet-shipped unit is moved. Exchange and claim replacements are moved only out of a named `source_fulfillment_id`, which is how a canceled replacement is sent again. Pass `status: 'shipped'` to register an already-shipped fulfillment (fires shipped webhooks and freezes cost/carrier). When `delivery_method_id` is omitted, the fulfillment inherits the delivery method and cost of the source fulfillment(s) it fully drains — keeping the order total unchanged; partially drained splits get no carrier when shipped, and pending fulfillments are otherwise (re)priced by the standard rate engine, which selects the lowest-cost available rate. Pass `cost` to set an explicit shipping cost instead (e.g. the 3PL price) — note this changes the order total and payment state, and is guaranteed to persist only with `status: 'shipped'` (pending fulfillments are re-priced by the rate engine).

        **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.create('or_UkLWZg9DAJ', {
            stock_location_id: 'sloc_UkLWZg9DAJ',
            tracking: 'INPOST-12345',
            delivery_method_id: 'dm_UkLWZg9DAJ',
            status: 'shipped',
            items: [{ item_id: 'li_UkLWZg9DAJ', quantity: 1 }],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{order_id}/fulfillments -d '{"stock_location_id":"sloc_UkLWZg9DAJ","tracking":"INPOST-12345","delivery_method_id":"dm_UkLWZg9DAJ","status":"shipped","items":[{"item_id":"li_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
      responses:
        '201':
          description: fulfillment created
          content:
            application/json:
              example:
                id: ful_gbHJdmfrXB
                number: R1001-F1
                tracking: INPOST-12345
                tracking_url:
                pickup_point_data:
                selected_delivery_rate_id: dr_EfhxLZ9ck8
                unpriced: false
                cost: '100.00'
                total: '100.00'
                discount_total: '0.00'
                additional_tax_total: '0.00'
                included_tax_total: '0.00'
                tax_total: '0.00'
                status: fulfilled
                fulfillment_type: shipping
                fulfilled_at: '2026-01-15T12:00:00.000Z'
                delivered_at:
                items:
                - item_id: li_UkLWZg9DAJ
                  variant_id: variant_UkLWZg9DAJ
                  quantity: 1
                deliveries:
                - id: dlv_gbHJdmfrXB
                  tracking_number: INPOST-12345
                  carrier:
                  carrier_name:
                  service:
                  status: pending
                  tracking_url:
                  estimated_delivery_at:
                  delivered_at:
                  details:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  shipping_label_id:
                external_references: {}
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                adjustment_total: '0.00'
                pre_tax_amount: '0.00'
                order_id: or_UkLWZg9DAJ
                stock_location_id: sloc_UkLWZg9DAJ
                documents: []
                labels: []
                provider_generates_labels: false
        '422':
          description: order not completed
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: Fulfillments can only be created manually on completed
                    orders
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/FulfillmentCreateParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/fulfillments/{id}
      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: R1001-F1
                tracking: U10000
                tracking_url:
                pickup_point_data:
                selected_delivery_rate_id: dr_gbHJdmfrXB
                unpriced: false
                cost: '100.00'
                total: '100.00'
                discount_total: '0.00'
                additional_tax_total: '0.00'
                included_tax_total: '0.00'
                tax_total: '0.00'
                status: unfulfilled
                fulfillment_type: shipping
                fulfilled_at:
                delivered_at:
                items:
                - item_id: li_UkLWZg9DAJ
                  variant_id: variant_UkLWZg9DAJ
                  quantity: 1
                deliveries:
                - id: dlv_UkLWZg9DAJ
                  tracking_number: U10000
                  carrier:
                  carrier_name:
                  service:
                  status: pending
                  tracking_url:
                  estimated_delivery_at:
                  delivered_at:
                  details:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  shipping_label_id:
                external_references: {}
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                adjustment_total: '0.00'
                pre_tax_amount: '100.00'
                order_id: or_UkLWZg9DAJ
                stock_location_id: sloc_UkLWZg9DAJ
                documents: []
                labels: []
                provider_generates_labels: false
    patch:
      summary: Update a shipment
      tags:
      - Fulfillments
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Updates a fulfillment (tracking, delivery 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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/fulfillments/{id} -d '{"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: R1001-F1
                tracking: 1Z999AA10123456784
                tracking_url: https://www.ups.com/track?tracknum=1Z999AA10123456784
                pickup_point_data:
                selected_delivery_rate_id: dr_gbHJdmfrXB
                unpriced: false
                cost: '100.00'
                total: '100.00'
                discount_total: '0.00'
                additional_tax_total: '0.00'
                included_tax_total: '0.00'
                tax_total: '0.00'
                status: unfulfilled
                fulfillment_type: shipping
                fulfilled_at:
                delivered_at:
                items:
                - item_id: li_UkLWZg9DAJ
                  variant_id: variant_UkLWZg9DAJ
                  quantity: 1
                deliveries:
                - id: dlv_UkLWZg9DAJ
                  tracking_number: 1Z999AA10123456784
                  carrier: ups
                  carrier_name: UPS
                  service:
                  status: pending
                  tracking_url: https://www.ups.com/track?tracknum=1Z999AA10123456784
                  estimated_delivery_at:
                  delivered_at:
                  details:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  shipping_label_id:
                external_references: {}
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                adjustment_total: '0.00'
                pre_tax_amount: '100.00'
                order_id: or_UkLWZg9DAJ
                stock_location_id: sloc_UkLWZg9DAJ
                documents: []
                labels: []
                provider_generates_labels: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/FulfillmentUpdateParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/fulfillments/{id}/fulfill -d '{
          ... }'
      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: R1001-F1
                tracking: 1Z999AA10123456784
                tracking_url: https://www.ups.com/track?tracknum=1Z999AA10123456784
                pickup_point_data:
                selected_delivery_rate_id: dr_gbHJdmfrXB
                unpriced: false
                cost: '100.00'
                total: '100.00'
                discount_total: '0.00'
                additional_tax_total: '0.00'
                included_tax_total: '0.00'
                tax_total: '0.00'
                status: fulfilled
                fulfillment_type: shipping
                fulfilled_at: '2026-01-15T12:00:00.000Z'
                delivered_at:
                items:
                - item_id: li_UkLWZg9DAJ
                  variant_id: variant_UkLWZg9DAJ
                  quantity: 1
                deliveries:
                - id: dlv_UkLWZg9DAJ
                  tracking_number: 1Z999AA10123456784
                  carrier: ups
                  carrier_name: UPS
                  service:
                  status: pending
                  tracking_url: https://www.ups.com/track?tracknum=1Z999AA10123456784
                  estimated_delivery_at:
                  delivered_at:
                  details:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  shipping_label_id:
                external_references: {}
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                adjustment_total: '0.00'
                pre_tax_amount: '100.00'
                order_id: or_UkLWZg9DAJ
                stock_location_id: sloc_UkLWZg9DAJ
                documents: []
                labels: []
                provider_generates_labels: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/FulfillmentFulfillParams"
  "/api/v3/admin/orders/{order_id}/fulfillments/{id}/mark_delivered":
    patch:
      summary: Mark a fulfillment delivered
      tags:
      - Fulfillments
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Records that the customer received the goods. Only a fulfilled shipment can be marked delivered.

        **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.markDelivered(
            'or_UkLWZg9DAJ',
            'ful_UkLWZg9DAJ',
            { delivered_at: '2026-08-11T09:30:00Z' },
          )
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/fulfillments/{id}/mark_delivered
          -d '{"delivered_at":"2026-08-11T09:30:00Z"}'
      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 delivered
          content:
            application/json:
              example:
                id: ful_UkLWZg9DAJ
                number: R1001-F1
                tracking: U10000
                tracking_url:
                pickup_point_data:
                selected_delivery_rate_id: dr_gbHJdmfrXB
                unpriced: false
                cost: '100.00'
                total: '100.00'
                discount_total: '0.00'
                additional_tax_total: '0.00'
                included_tax_total: '0.00'
                tax_total: '0.00'
                status: delivered
                fulfillment_type: shipping
                fulfilled_at: '2026-01-15T12:00:00.000Z'
                delivered_at: '2026-01-15T12:00:00.000Z'
                items:
                - item_id: li_UkLWZg9DAJ
                  variant_id: variant_UkLWZg9DAJ
                  quantity: 1
                deliveries:
                - id: dlv_UkLWZg9DAJ
                  tracking_number: U10000
                  carrier:
                  carrier_name:
                  service:
                  status: delivered
                  tracking_url:
                  estimated_delivery_at:
                  delivered_at: '2026-01-15T12:00:00.000Z'
                  details:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  shipping_label_id:
                external_references: {}
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                adjustment_total: '0.00'
                pre_tax_amount: '100.00'
                order_id: or_UkLWZg9DAJ
                stock_location_id: sloc_UkLWZg9DAJ
                documents: []
                labels: []
                provider_generates_labels: false
        '422':
          description: fulfillment has not shipped
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: Only a fulfilled shipment can be marked delivered
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/FulfillmentMarkDeliveredParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/fulfillments/{id}/cancel -d '{
          ... }'
      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: R1001-F1
                tracking: U10000
                tracking_url:
                pickup_point_data:
                selected_delivery_rate_id: dr_gbHJdmfrXB
                unpriced: false
                cost: '100.00'
                total: '100.00'
                discount_total: '0.00'
                additional_tax_total: '0.00'
                included_tax_total: '0.00'
                tax_total: '0.00'
                status: canceled
                fulfillment_type: shipping
                fulfilled_at:
                delivered_at:
                items:
                - item_id: li_UkLWZg9DAJ
                  variant_id: variant_UkLWZg9DAJ
                  quantity: 1
                deliveries:
                - id: dlv_UkLWZg9DAJ
                  tracking_number: U10000
                  carrier:
                  carrier_name:
                  service:
                  status: pending
                  tracking_url:
                  estimated_delivery_at:
                  delivered_at:
                  details:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  shipping_label_id:
                external_references: {}
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                adjustment_total: '0.00'
                pre_tax_amount: '100.00'
                order_id: or_UkLWZg9DAJ
                stock_location_id: sloc_UkLWZg9DAJ
                documents: []
                labels: []
                provider_generates_labels: false
  "/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',
          })

          // Splitting moves a quantity of one variant into its own fulfillment, so the
          // response is the order's full set: the source is re-shaped, and disappears
          // when the split drains it. Pass stock_location_id to send the new
          // fulfillment out from a different origin.
          const { data: fulfillments } = await client.orders.fulfillments.split(
            'or_UkLWZg9DAJ',
            'ful_UkLWZg9DAJ',
            {
              variant_id: 'variant_86Rf07xd4z',
              quantity: 1,
            },
          )
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/fulfillments/{id}/split -d '{"variant_id":"variant_86Rf07xd4z","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: R1001-F1
                  tracking:
                  tracking_url:
                  pickup_point_data:
                  selected_delivery_rate_id: dr_EfhxLZ9ck8
                  unpriced: false
                  cost: '10.00'
                  total: '10.00'
                  discount_total: '0.00'
                  additional_tax_total: '0.00'
                  included_tax_total: '0.00'
                  tax_total: '0.00'
                  status: unfulfilled
                  fulfillment_type: shipping
                  fulfilled_at:
                  delivered_at:
                  items:
                  - item_id: li_UkLWZg9DAJ
                    variant_id: variant_UkLWZg9DAJ
                    quantity: 1
                  deliveries: []
                  external_references: {}
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  adjustment_total: '0.00'
                  pre_tax_amount: '0.00'
                  order_id: or_UkLWZg9DAJ
                  stock_location_id: sloc_gbHJdmfrXB
                  documents: []
                  labels: []
                  provider_generates_labels: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/FulfillmentSplitParams"
        required: true
  "/api/v3/admin/gift_cards/{gift_card_id}/custom_fields":
    get:
      summary: List gift card custom fields
      tags:
      - Gift Cards
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the gift card's custom field values.

        **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: customFields } = await client.customFields('gift_card', 'gc_UkLWZg9DAJ').list()
      - lang: bash
        label: Spree CLI
        source: spree api get /gift_cards/{gift_card_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: gift_card_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/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 })
      - lang: bash
        label: Spree CLI
        source: spree api get /gift_card_batches -d '{"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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: sort
        in: query
        required: false
        description: Sort by field. Prefix with `-` for descending.
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[prefix_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `prefix` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `prefix`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: GiftCardBatch
        sortable:
        - created_at
        - id
        - prefix
        - updated_at
      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-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  amount: '50.00'
                  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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /gift_card_batches -d '{"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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                amount: '25.00'
                expires_at: '2030-12-31'
                created_by_id: adm_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:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/GiftCardBatchCreateParams"
        required: 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')
      - lang: bash
        label: Spree CLI
        source: spree api get /gift_card_batches/{id}
      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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                amount: '50.00'
                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[customer_id_eq]` for cards issued
        to a specific customer, or `q[status_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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /gift_cards -d '{"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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of code (partial, case-insensitive).
      - name: q[active]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `active`.
      - name: q[expired]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `expired`.
      - name: q[partially_redeemed]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `partially_redeemed`.
      - name: q[redeemed]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `redeemed`.
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - 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
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[code_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_by_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `currency` | One of the `CurrencyCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `customer_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `expires_at` | Date | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `gift_card_batch_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `state` | One of `active`, `partially_redeemed`, `redeemed`, `canceled` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `status` | One of `active`, `partially_redeemed`, `redeemed`, `canceled` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[batch_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `batch_` | `created_at`, `id`, `prefix`, `updated_at` |
          | `customers_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `customers_addresses_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customers_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customers_customer_groups_` | `created_at`, `id`, `name`, `updated_at` |
          | `customers_orders_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `customers_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customers_spree_roles_` | `created_at`, `id`, `name`, `updated_at` |
          | `customers_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `orders_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `orders_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `orders_channel_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `orders_customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `orders_fulfillments_` | `created_at`, `id`, `number`, `updated_at` |
          | `orders_line_items_` | `additional_tax_total`, `adjustment_total`, `cost_price`, `created_at`, `discount_total`, `id`, `included_tax_total`, `non_taxable_adjustment_total`, `order_id`, `pre_tax_amount`, `price`, `quantity`, `tax_category_id`, `taxable_adjustment_total`, `updated_at`, `variant_id` |
          | `orders_order_group_` | `created_at`, `currency`, `email`, `id`, `number`, `updated_at` |
          | `orders_promotions_` | `code`, `created_at`, `expires_at`, `id`, `kind`, `name`, `path`, `promotion_category_id`, `starts_at`, `updated_at` |
          | `orders_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `orders_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `orders_shipments_` | `created_at`, `id`, `number`, `updated_at` |
          | `orders_store_` | `created_at`, `id`, `name`, `updated_at` |
          | `orders_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `users_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `users_addresses_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `users_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `users_customer_groups_` | `created_at`, `id`, `name`, `updated_at` |
          | `users_orders_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `users_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `users_spree_roles_` | `created_at`, `id`, `name`, `updated_at` |
          | `users_tags_` | `created_at`, `id`, `name`, `updated_at` |

          </Accordion>

          **Sort by:** `code`, `created_at`, `created_by_id`, `currency`, `customer_id`, `expires_at`, `gift_card_batch_id`, `id`, `state`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: GiftCard
        sortable:
        - code
        - created_at
        - created_by_id
        - currency
        - customer_id
        - expires_at
        - gift_card_batch_id
        - id
        - state
        - status
        - updated_at
      responses:
        '200':
          description: gift cards found
          content:
            application/json:
              example:
                data:
                - id: gc_UkLWZg9DAJ
                  code: C5BC700C4EF16A06
                  status: active
                  currency: USD
                  amount: '50.00'
                  amount_used: '0.00'
                  amount_authorized: '0.00'
                  amount_remaining: '50.00'
                  expires_at:
                  redeemed_at:
                  expired: false
                  active: true
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  customer_id:
                  created_by_id:
                - id: gc_gbHJdmfrXB
                  code: 3BECEA5A776AD146
                  status: active
                  currency: USD
                  amount: '25.00'
                  amount_used: '0.00'
                  amount_authorized: '0.00'
                  amount_remaining: '25.00'
                  expires_at:
                  redeemed_at:
                  expired: false
                  active: true
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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 `customer_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',
            customer_id: 'cus_UkLWZg9DAJ',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /gift_cards -d '{"amount":"25.00","currency":"USD","expires_at":"2030-12-31","customer_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: A68048412201A26B
                status: active
                currency: USD
                amount: '25.00'
                amount_used: '0.00'
                amount_authorized: '0.00'
                amount_remaining: '25.00'
                expires_at: '2030-12-31'
                redeemed_at:
                expired: false
                active: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                customer_id:
                created_by_id: adm_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:
                    - value: '0.0'
                      count: 0
                      code: greater_than
                      message: must be greater than 0
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/GiftCardCreateParams"
        required: 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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /gift_cards/{id} -d '{"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: 06BEABE5C26AA7E5
                status: active
                currency: USD
                amount: '50.00'
                amount_used: '0.00'
                amount_authorized: '0.00'
                amount_remaining: '50.00'
                expires_at:
                redeemed_at:
                expired: false
                active: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /gift_cards/{id} -d '{"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: E34E66F15D82A3CD
                status: active
                currency: USD
                amount: '75.00'
                amount_used: '0.00'
                amount_authorized: '0.00'
                amount_remaining: '75.00'
                expires_at:
                redeemed_at:
                expired: false
                active: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                customer_id:
                created_by_id:
              schema:
                "$ref": "#/components/schemas/GiftCard"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/GiftCardUpdateParams"
        required: 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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /gift_cards/{id}
      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/imports":
    get:
      summary: List imports
      tags:
      - Imports
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns CSV imports queued or completed for the current store.

        **Required scope:** the write scope of the imported resource — `write_products` for product imports, `write_customers` for customer imports, 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: imports } = await client.imports.list({
            status_eq: 'failed',
            sort: '-created_at',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /imports -d '{"status_eq":"failed","sort":"-created_at"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of number (partial, case-insensitive).
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `seller_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `status` | One of `pending`, `mapping`, `completed_mapping`, `processing`, `completed`, `failed` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `type` | Type | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[seller_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |

          </Accordion>

          **Sort by:** `created_at`, `id`, `number`, `seller_id`, `status`, `type`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Import
        sortable:
        - created_at
        - id
        - number
        - seller_id
        - status
        - type
        - updated_at
      responses:
        '200':
          description: imports found
          content:
            application/json:
              example:
                data:
                - id: imp_UkLWZg9DAJ
                  number: IM1001
                  rows_count: 0
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  type: products
                  status: pending
                  store_id: store_UkLWZg9DAJ
                  seller_id:
                  user_id: adm_UkLWZg9DAJ
                  processing_errors:
                  delimiter: ","
                  price_list_id:
                  seller_name:
                  original_filename: products_import.csv
                  original_byte_size: 3627
                  original_file_url: "/api/v3/admin/imports/imp_UkLWZg9DAJ/download"
                  completed_rows_count: 0
                  failed_rows_count: 0
                  schema_fields:
                  - name: slug
                    label: Slug
                    required: true
                  - name: sku
                    label: SKU
                    required: true
                  - name: name
                    label: Name
                    required: true
                  - name: price
                    label: Price
                    required: true
                  - name: status
                    label: Status
                    required: false
                  - name: description
                    label: Description
                    required: false
                  - name: meta_title
                    label: Meta Title
                    required: false
                  - name: meta_description
                    label: Meta Description
                    required: false
                  - name: meta_keywords
                    label: Meta Keywords
                    required: false
                  - name: tags
                    label: Tags
                    required: false
                  - name: compare_at_price
                    label: Compare at Price
                    required: false
                  - name: currency
                    label: Currency
                    required: false
                  - name: width
                    label: Width
                    required: false
                  - name: height
                    label: Height
                    required: false
                  - name: depth
                    label: Depth
                    required: false
                  - name: dimensions_unit
                    label: Dimensions Unit
                    required: false
                  - name: weight
                    label: Weight
                    required: false
                  - name: weight_unit
                    label: Weight Unit
                    required: false
                  - name: available_on
                    label: Available On
                    required: false
                  - name: discontinue_on
                    label: Discontinue On
                    required: false
                  - name: track_inventory
                    label: Track Inventory
                    required: false
                  - name: inventory_count
                    label: Inventory Count
                    required: false
                  - name: inventory_backorderable
                    label: Inventory Backorderable
                    required: false
                  - name: stock_location
                    label: Stock Location
                    required: false
                  - name: tax_category
                    label: Tax Category
                    required: false
                  - name: product_type
                    label: Product Type
                    required: false
                  - name: hs_code
                    label: HS Code
                    required: false
                  - name: country_of_origin
                    label: Country of Origin
                    required: false
                  - name: customs_description
                    label: Customs Description
                    required: false
                  - name: carton
                    label: Carton
                    required: false
                  - name: units_per_carton
                    label: Units per Carton
                    required: false
                  - name: carton_weight
                    label: Carton Weight
                    required: false
                  - name: cartons_per_pallet
                    label: Cartons per Pallet
                    required: false
                  - name: image1_src
                    label: Image 1 URL
                    required: false
                  - name: image2_src
                    label: Image 2 URL
                    required: false
                  - name: image3_src
                    label: Image 3 URL
                    required: false
                  - name: option1_name
                    label: Option 1 Name
                    required: false
                  - name: option1_value
                    label: Option 1 Value
                    required: false
                  - name: option2_name
                    label: Option 2 Name
                    required: false
                  - name: option2_value
                    label: Option 2 Value
                    required: false
                  - name: option3_name
                    label: Option 3 Name
                    required: false
                  - name: option3_value
                    label: Option 3 Value
                    required: false
                  - name: category1
                    label: Category 1
                    required: false
                  - name: category2
                    label: Category 2
                    required: false
                  - name: category3
                    label: Category 3
                    required: false
                  csv_headers: []
                  sample_row: {}
                  mappings: []
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Create an import
      tags:
      - Imports
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Queues a CSV import. Upload the file first via `POST /api/v3/admin/files`
        and pass the returned `signed_id` as `attachment_signed_id`. On success the import is in the
        `mapping` state and the response carries the mapping payload: `schema_fields`
        (the canonical columns for the type), `csv_headers`, a `sample_row`, and the
        auto-assigned `mappings`.

        Adjust mappings if needed, then call `PATCH /admin/imports/{id}/complete_mapping`
        to start processing. Poll `GET /admin/imports/{id}` while `status` is
        `completed_mapping`/`processing`; terminal statuses are `completed` and `failed`.


        **Required scope:** the write scope of the imported resource — `write_products` for product imports, `write_customers` for customer imports, 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',
          })

          // Upload the CSV with `client.files.upload(file, { visibility: 'private' })`
          // first and pass its `signed_id`. The import then waits in `mapping`, with the
          // columns assigned automatically.
          const productImport = await client.imports.create({
            type: 'products',
            attachment_signed_id: 'eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--a1b2c3',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /imports -d '{"type":"products","attachment_signed_id":"eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--a1b2c3"}'
      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: import created in mapping state
          content:
            application/json:
              example:
                id: imp_gbHJdmfrXB
                number: IM1002
                rows_count: 0
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: products
                status: mapping
                store_id: store_UkLWZg9DAJ
                seller_id:
                user_id: adm_UkLWZg9DAJ
                processing_errors:
                delimiter: ","
                price_list_id:
                seller_name:
                original_filename: import.csv
                original_byte_size: 44
                original_file_url: "/api/v3/admin/imports/imp_gbHJdmfrXB/download"
                completed_rows_count: 0
                failed_rows_count: 0
                schema_fields:
                - name: slug
                  label: Slug
                  required: true
                - name: sku
                  label: SKU
                  required: true
                - name: name
                  label: Name
                  required: true
                - name: price
                  label: Price
                  required: true
                - name: status
                  label: Status
                  required: false
                - name: description
                  label: Description
                  required: false
                - name: meta_title
                  label: Meta Title
                  required: false
                - name: meta_description
                  label: Meta Description
                  required: false
                - name: meta_keywords
                  label: Meta Keywords
                  required: false
                - name: tags
                  label: Tags
                  required: false
                - name: compare_at_price
                  label: Compare at Price
                  required: false
                - name: currency
                  label: Currency
                  required: false
                - name: width
                  label: Width
                  required: false
                - name: height
                  label: Height
                  required: false
                - name: depth
                  label: Depth
                  required: false
                - name: dimensions_unit
                  label: Dimensions Unit
                  required: false
                - name: weight
                  label: Weight
                  required: false
                - name: weight_unit
                  label: Weight Unit
                  required: false
                - name: available_on
                  label: Available On
                  required: false
                - name: discontinue_on
                  label: Discontinue On
                  required: false
                - name: track_inventory
                  label: Track Inventory
                  required: false
                - name: inventory_count
                  label: Inventory Count
                  required: false
                - name: inventory_backorderable
                  label: Inventory Backorderable
                  required: false
                - name: stock_location
                  label: Stock Location
                  required: false
                - name: tax_category
                  label: Tax Category
                  required: false
                - name: product_type
                  label: Product Type
                  required: false
                - name: hs_code
                  label: HS Code
                  required: false
                - name: country_of_origin
                  label: Country of Origin
                  required: false
                - name: customs_description
                  label: Customs Description
                  required: false
                - name: carton
                  label: Carton
                  required: false
                - name: units_per_carton
                  label: Units per Carton
                  required: false
                - name: carton_weight
                  label: Carton Weight
                  required: false
                - name: cartons_per_pallet
                  label: Cartons per Pallet
                  required: false
                - name: image1_src
                  label: Image 1 URL
                  required: false
                - name: image2_src
                  label: Image 2 URL
                  required: false
                - name: image3_src
                  label: Image 3 URL
                  required: false
                - name: option1_name
                  label: Option 1 Name
                  required: false
                - name: option1_value
                  label: Option 1 Value
                  required: false
                - name: option2_name
                  label: Option 2 Name
                  required: false
                - name: option2_value
                  label: Option 2 Value
                  required: false
                - name: option3_name
                  label: Option 3 Name
                  required: false
                - name: option3_value
                  label: Option 3 Value
                  required: false
                - name: category1
                  label: Category 1
                  required: false
                - name: category2
                  label: Category 2
                  required: false
                - name: category3
                  label: Category 3
                  required: false
                csv_headers:
                - slug
                - sku
                - name
                - price
                sample_row:
                  slug: widget
                  sku: W-1
                  name: Widget
                  price: '10.00'
                mappings:
                - id: immap_UkLWZg9DAJ
                  schema_field: slug
                  file_column: slug
                  required: true
                - id: immap_gbHJdmfrXB
                  schema_field: sku
                  file_column: sku
                  required: true
                - id: immap_EfhxLZ9ck8
                  schema_field: name
                  file_column: name
                  required: true
                - id: immap_VqXmZF31wY
                  schema_field: price
                  file_column: price
                  required: true
                - id: immap_uw2YK1rnl0
                  schema_field: status
                  file_column:
                  required: false
                - id: immap_OIJLhNcSbf
                  schema_field: description
                  file_column:
                  required: false
                - id: immap_AXs1igzRC6
                  schema_field: meta_title
                  file_column:
                  required: false
                - id: immap_p6klVeMgbn
                  schema_field: meta_description
                  file_column:
                  required: false
                - id: immap_nJqfPa3Cpe
                  schema_field: meta_keywords
                  file_column:
                  required: false
                - id: immap_98FqgRua4h
                  schema_field: tags
                  file_column:
                  required: false
                - id: immap_xhoCpeNMWu
                  schema_field: compare_at_price
                  file_column:
                  required: false
                - id: immap_vEmzDoNU0H
                  schema_field: currency
                  file_column:
                  required: false
                - id: immap_2KY5XM6frI
                  schema_field: width
                  file_column:
                  required: false
                - id: immap_HOVtlDrOmL
                  schema_field: height
                  file_column:
                  required: false
                - id: immap_ed6l8wVqSM
                  schema_field: depth
                  file_column:
                  required: false
                - id: immap_s18jaGonyx
                  schema_field: dimensions_unit
                  file_column:
                  required: false
                - id: immap_GZUcnUYI5A
                  schema_field: weight
                  file_column:
                  required: false
                - id: immap_ROeNhrwyV9
                  schema_field: weight_unit
                  file_column:
                  required: false
                - id: immap_L3pHOn63Vw
                  schema_field: available_on
                  file_column:
                  required: false
                - id: immap_PQNMcnNFWw
                  schema_field: discontinue_on
                  file_column:
                  required: false
                - id: immap_C9SrJgpzQ4
                  schema_field: track_inventory
                  file_column:
                  required: false
                - id: immap_YHETxCGlb0
                  schema_field: inventory_count
                  file_column:
                  required: false
                - id: immap_5OQZnCRf8J
                  schema_field: inventory_backorderable
                  file_column:
                  required: false
                - id: immap_F0GX8NaP3Y
                  schema_field: stock_location
                  file_column:
                  required: false
                - id: immap_kOKT9MVfb0
                  schema_field: tax_category
                  file_column:
                  required: false
                - id: immap_3uWpPTcf5W
                  schema_field: product_type
                  file_column:
                  required: false
                - id: immap_D6Psx31WaT
                  schema_field: hs_code
                  file_column:
                  required: false
                - id: immap_msx3nOJap6
                  schema_field: country_of_origin
                  file_column:
                  required: false
                - id: immap_5CQZnCRf8J
                  schema_field: customs_description
                  file_column:
                  required: false
                - id: immap_M2nyloHRUQ
                  schema_field: carton
                  file_column:
                  required: false
                - id: immap_prklVeMgbn
                  schema_field: units_per_carton
                  file_column:
                  required: false
                - id: immap_so8jaGonyx
                  schema_field: carton_weight
                  file_column:
                  required: false
                - id: immap_rsClYtECFI
                  schema_field: cartons_per_pallet
                  file_column:
                  required: false
                - id: immap_8DR0I7fEbw
                  schema_field: image1_src
                  file_column:
                  required: false
                - id: immap_aAtNvLSUAr
                  schema_field: image2_src
                  file_column:
                  required: false
                - id: immap_QiA48cIW7A
                  schema_field: image3_src
                  file_column:
                  required: false
                - id: immap_QDA48cIW7A
                  schema_field: option1_name
                  file_column:
                  required: false
                - id: immap_8cR0I7fEbw
                  schema_field: option1_value
                  file_column:
                  required: false
                - id: immap_oqlrKdXjaP
                  schema_field: option2_name
                  file_column:
                  required: false
                - id: immap_48Olu6p4zZ
                  schema_field: option2_value
                  file_column:
                  required: false
                - id: immap_qp31JYFduR
                  schema_field: option3_name
                  file_column:
                  required: false
                - id: immap_JgaEBgznCp
                  schema_field: option3_value
                  file_column:
                  required: false
                - id: immap_tXyJwvFCuK
                  schema_field: category1
                  file_column:
                  required: false
                - id: immap_NJzXvxTk8u
                  schema_field: category2
                  file_column:
                  required: false
                - id: immap_XLbb5HTmVa
                  schema_field: category3
                  file_column:
                  required: false
        '422':
          description: unknown import type
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Type can't be blank
                  details:
                    type:
                    - code: blank
                      message: can't be blank
                      specific: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ImportCreateParams"
        required: true
  "/api/v3/admin/imports/template":
    get:
      summary: Download an import template
      tags:
      - Imports
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a CSV header row for the given import type, including the custom field columns available for the model.

        **Required scope:** the write scope of the imported resource — `write_products` for product imports, `write_customers` for customer imports, 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',
          })

          // The template is a CSV, so fetch it directly with the API key:
          const response = await fetch('https://your-store.com/api/v3/admin/imports/template?type=products', {
            headers: { 'X-Spree-API-Key': 'sk_xxx' },
          })
          if (!response.ok) throw new Error(`Download failed with status ${response.status}`)
          const csvHeader = await response.text()
      - lang: bash
        label: Spree CLI
        source: spree api get /imports/template
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: type
        in: query
        required: true
        description: Registered import type, e.g. products.
        schema:
          type: string
      responses:
        '200':
          description: CSV template
          content:
            text/csv:
              schema:
                type: string
                format: binary
  "/api/v3/admin/imports/example":
    get:
      summary: Download an example import file
      tags:
      - Imports
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Redirects to a populated example CSV for the given import type — the same sample data `rake spree:load_sample_data` uses, pinned to the installed Spree version. Returns 404 for a type that ships no example file.

        **Required scope:** the write scope of the imported resource — `write_products` for product imports, `write_customers` for customer imports, 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',
          })

          // Redirects to a populated example CSV; fetch follows the redirect.
          const response = await fetch('https://your-store.com/api/v3/admin/imports/example?type=products', {
            headers: { 'X-Spree-API-Key': 'sk_xxx' },
          })
          if (!response.ok) throw new Error(`Download failed with status ${response.status}`)
          const exampleCsv = await response.text()
      - lang: bash
        label: Spree CLI
        source: spree api get /imports/example
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: type
        in: query
        required: true
        description: Registered import type, e.g. products.
        schema:
          type: string
      responses:
        '302':
          description: Redirect to the example CSV
  "/api/v3/admin/imports/{id}":
    get:
      summary: Show an import
      tags:
      - Imports
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns import status and row counters. The admin dashboard polls this endpoint while `status` is `completed_mapping` or `processing`; `rows_count`, `completed_rows_count` and `failed_rows_count` drive the progress bar. The mapping payload (`csv_headers`, `sample_row`) is only present while `status` is `mapping`.

        **Required scope:** the write scope of the imported resource — `write_products` for product imports, `write_customers` for customer imports, 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 productImport = await client.imports.get('imp_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /imports/{id}
      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: import found
          content:
            application/json:
              example:
                id: imp_UkLWZg9DAJ
                number: IM1001
                rows_count: 0
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: products
                status: pending
                store_id: store_UkLWZg9DAJ
                seller_id:
                user_id: adm_UkLWZg9DAJ
                processing_errors:
                delimiter: ","
                price_list_id:
                seller_name:
                original_filename: products_import.csv
                original_byte_size: 3627
                original_file_url: "/api/v3/admin/imports/imp_UkLWZg9DAJ/download"
                completed_rows_count: 0
                failed_rows_count: 0
                schema_fields:
                - name: slug
                  label: Slug
                  required: true
                - name: sku
                  label: SKU
                  required: true
                - name: name
                  label: Name
                  required: true
                - name: price
                  label: Price
                  required: true
                - name: status
                  label: Status
                  required: false
                - name: description
                  label: Description
                  required: false
                - name: meta_title
                  label: Meta Title
                  required: false
                - name: meta_description
                  label: Meta Description
                  required: false
                - name: meta_keywords
                  label: Meta Keywords
                  required: false
                - name: tags
                  label: Tags
                  required: false
                - name: compare_at_price
                  label: Compare at Price
                  required: false
                - name: currency
                  label: Currency
                  required: false
                - name: width
                  label: Width
                  required: false
                - name: height
                  label: Height
                  required: false
                - name: depth
                  label: Depth
                  required: false
                - name: dimensions_unit
                  label: Dimensions Unit
                  required: false
                - name: weight
                  label: Weight
                  required: false
                - name: weight_unit
                  label: Weight Unit
                  required: false
                - name: available_on
                  label: Available On
                  required: false
                - name: discontinue_on
                  label: Discontinue On
                  required: false
                - name: track_inventory
                  label: Track Inventory
                  required: false
                - name: inventory_count
                  label: Inventory Count
                  required: false
                - name: inventory_backorderable
                  label: Inventory Backorderable
                  required: false
                - name: stock_location
                  label: Stock Location
                  required: false
                - name: tax_category
                  label: Tax Category
                  required: false
                - name: product_type
                  label: Product Type
                  required: false
                - name: hs_code
                  label: HS Code
                  required: false
                - name: country_of_origin
                  label: Country of Origin
                  required: false
                - name: customs_description
                  label: Customs Description
                  required: false
                - name: carton
                  label: Carton
                  required: false
                - name: units_per_carton
                  label: Units per Carton
                  required: false
                - name: carton_weight
                  label: Carton Weight
                  required: false
                - name: cartons_per_pallet
                  label: Cartons per Pallet
                  required: false
                - name: image1_src
                  label: Image 1 URL
                  required: false
                - name: image2_src
                  label: Image 2 URL
                  required: false
                - name: image3_src
                  label: Image 3 URL
                  required: false
                - name: option1_name
                  label: Option 1 Name
                  required: false
                - name: option1_value
                  label: Option 1 Value
                  required: false
                - name: option2_name
                  label: Option 2 Name
                  required: false
                - name: option2_value
                  label: Option 2 Value
                  required: false
                - name: option3_name
                  label: Option 3 Name
                  required: false
                - name: option3_value
                  label: Option 3 Value
                  required: false
                - name: category1
                  label: Category 1
                  required: false
                - name: category2
                  label: Category 2
                  required: false
                - name: category3
                  label: Category 3
                  required: false
                csv_headers: []
                sample_row: {}
                mappings: []
    delete:
      summary: Delete an import
      tags:
      - Imports
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Removes the import, its rows and the uploaded file. Returns 422 while the import is being processed.

        **Required scope:** the write scope of the imported resource — `write_products` for product imports, `write_customers` for customer imports, 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.imports.delete('imp_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /imports/{id}
      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: import deleted
  "/api/v3/admin/imports/{id}/download":
    get:
      summary: Download the originally uploaded file
      tags:
      - Imports
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Streams the CSV exactly as it was uploaded — the audit trail for what was imported. JWT/API-key protected; SPA clients fetch it with the Authorization header and trigger the browser download via a Blob URL.

        **Required scope:** the write scope of the imported resource — `write_products` for product imports, `write_customers` for customer imports, 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 productImport = await client.imports.get('imp_UkLWZg9DAJ')

          if (productImport.original_file_url) {
            // The uploaded file is served through the API, so fetch it with the API key:
            const response = await fetch(`https://your-store.com${productImport.original_file_url}`, {
              headers: { 'X-Spree-API-Key': 'sk_xxx' },
            })
            if (!response.ok) throw new Error(`Download failed with status ${response.status}`)
            const csv = await response.text()
            console.log(csv)
          }
      - lang: bash
        label: Spree CLI
        source: spree api get /imports/{id}/download
      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:
            text/csv:
              schema:
                type: string
                format: binary
  "/api/v3/admin/imports/{id}/complete_mapping":
    patch:
      summary: Complete mapping and start processing
      tags:
      - Imports
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Applies the submitted column mappings, then starts row processing. Omit `mappings`
        to accept the auto-assigned ones from the create response. Returns 422 when a
        required schema field is left unmapped (`details.missing_required_fields`) or a
        file column is assigned twice.


        **Required scope:** the write scope of the imported resource — `write_products` for product imports, `write_customers` for customer imports, 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',
          })

          // Omit `mappings` to accept the columns assigned on create.
          const productImport = await client.imports.completeMapping('imp_UkLWZg9DAJ', {
            mappings: [
              { schema_field: 'slug', file_column: 'handle' },
              { schema_field: 'price', file_column: 'price_usd' },
            ],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /imports/{id}/complete_mapping -d '{"mappings":[{"schema_field":"slug","file_column":"handle"},{"schema_field":"price","file_column":"price_usd"}]}'
      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: mapping completed, processing queued
          content:
            application/json:
              example:
                id: imp_gbHJdmfrXB
                number: IM1002
                rows_count: 0
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: products
                status: completed_mapping
                store_id: store_UkLWZg9DAJ
                seller_id:
                user_id: adm_UkLWZg9DAJ
                processing_errors:
                delimiter: ","
                price_list_id:
                seller_name:
                original_filename: products_import.csv
                original_byte_size: 3627
                original_file_url: "/api/v3/admin/imports/imp_gbHJdmfrXB/download"
                completed_rows_count: 0
                failed_rows_count: 0
                schema_fields:
                - name: slug
                  label: Slug
                  required: true
                - name: sku
                  label: SKU
                  required: true
                - name: name
                  label: Name
                  required: true
                - name: price
                  label: Price
                  required: true
                - name: status
                  label: Status
                  required: false
                - name: description
                  label: Description
                  required: false
                - name: meta_title
                  label: Meta Title
                  required: false
                - name: meta_description
                  label: Meta Description
                  required: false
                - name: meta_keywords
                  label: Meta Keywords
                  required: false
                - name: tags
                  label: Tags
                  required: false
                - name: compare_at_price
                  label: Compare at Price
                  required: false
                - name: currency
                  label: Currency
                  required: false
                - name: width
                  label: Width
                  required: false
                - name: height
                  label: Height
                  required: false
                - name: depth
                  label: Depth
                  required: false
                - name: dimensions_unit
                  label: Dimensions Unit
                  required: false
                - name: weight
                  label: Weight
                  required: false
                - name: weight_unit
                  label: Weight Unit
                  required: false
                - name: available_on
                  label: Available On
                  required: false
                - name: discontinue_on
                  label: Discontinue On
                  required: false
                - name: track_inventory
                  label: Track Inventory
                  required: false
                - name: inventory_count
                  label: Inventory Count
                  required: false
                - name: inventory_backorderable
                  label: Inventory Backorderable
                  required: false
                - name: stock_location
                  label: Stock Location
                  required: false
                - name: tax_category
                  label: Tax Category
                  required: false
                - name: product_type
                  label: Product Type
                  required: false
                - name: hs_code
                  label: HS Code
                  required: false
                - name: country_of_origin
                  label: Country of Origin
                  required: false
                - name: customs_description
                  label: Customs Description
                  required: false
                - name: carton
                  label: Carton
                  required: false
                - name: units_per_carton
                  label: Units per Carton
                  required: false
                - name: carton_weight
                  label: Carton Weight
                  required: false
                - name: cartons_per_pallet
                  label: Cartons per Pallet
                  required: false
                - name: image1_src
                  label: Image 1 URL
                  required: false
                - name: image2_src
                  label: Image 2 URL
                  required: false
                - name: image3_src
                  label: Image 3 URL
                  required: false
                - name: option1_name
                  label: Option 1 Name
                  required: false
                - name: option1_value
                  label: Option 1 Value
                  required: false
                - name: option2_name
                  label: Option 2 Name
                  required: false
                - name: option2_value
                  label: Option 2 Value
                  required: false
                - name: option3_name
                  label: Option 3 Name
                  required: false
                - name: option3_value
                  label: Option 3 Value
                  required: false
                - name: category1
                  label: Category 1
                  required: false
                - name: category2
                  label: Category 2
                  required: false
                - name: category3
                  label: Category 3
                  required: false
                csv_headers: []
                sample_row: {}
                mappings:
                - id: immap_UkLWZg9DAJ
                  schema_field: slug
                  file_column: slug
                  required: true
                - id: immap_gbHJdmfrXB
                  schema_field: sku
                  file_column: sku
                  required: true
                - id: immap_EfhxLZ9ck8
                  schema_field: name
                  file_column: name
                  required: true
                - id: immap_VqXmZF31wY
                  schema_field: price
                  file_column: price
                  required: true
                - id: immap_uw2YK1rnl0
                  schema_field: status
                  file_column: status
                  required: false
                - id: immap_OIJLhNcSbf
                  schema_field: description
                  file_column: description
                  required: false
                - id: immap_AXs1igzRC6
                  schema_field: meta_title
                  file_column: meta_title
                  required: false
                - id: immap_p6klVeMgbn
                  schema_field: meta_description
                  file_column: meta_description
                  required: false
                - id: immap_nJqfPa3Cpe
                  schema_field: meta_keywords
                  file_column: meta_keywords
                  required: false
                - id: immap_98FqgRua4h
                  schema_field: tags
                  file_column: tags
                  required: false
                - id: immap_xhoCpeNMWu
                  schema_field: compare_at_price
                  file_column: compare_at_price
                  required: false
                - id: immap_vEmzDoNU0H
                  schema_field: currency
                  file_column: currency
                  required: false
                - id: immap_2KY5XM6frI
                  schema_field: width
                  file_column: width
                  required: false
                - id: immap_HOVtlDrOmL
                  schema_field: height
                  file_column: height
                  required: false
                - id: immap_ed6l8wVqSM
                  schema_field: depth
                  file_column: depth
                  required: false
                - id: immap_s18jaGonyx
                  schema_field: dimensions_unit
                  file_column: dimensions_unit
                  required: false
                - id: immap_GZUcnUYI5A
                  schema_field: weight
                  file_column: weight
                  required: false
                - id: immap_ROeNhrwyV9
                  schema_field: weight_unit
                  file_column: weight_unit
                  required: false
                - id: immap_L3pHOn63Vw
                  schema_field: available_on
                  file_column: available_on
                  required: false
                - id: immap_PQNMcnNFWw
                  schema_field: discontinue_on
                  file_column: discontinue_on
                  required: false
                - id: immap_C9SrJgpzQ4
                  schema_field: track_inventory
                  file_column: track_inventory
                  required: false
                - id: immap_YHETxCGlb0
                  schema_field: inventory_count
                  file_column: inventory_count
                  required: false
                - id: immap_5OQZnCRf8J
                  schema_field: inventory_backorderable
                  file_column: inventory_backorderable
                  required: false
                - id: immap_F0GX8NaP3Y
                  schema_field: stock_location
                  file_column:
                  required: false
                - id: immap_kOKT9MVfb0
                  schema_field: tax_category
                  file_column: tax_category
                  required: false
                - id: immap_3uWpPTcf5W
                  schema_field: product_type
                  file_column:
                  required: false
                - id: immap_D6Psx31WaT
                  schema_field: hs_code
                  file_column:
                  required: false
                - id: immap_msx3nOJap6
                  schema_field: country_of_origin
                  file_column:
                  required: false
                - id: immap_5CQZnCRf8J
                  schema_field: customs_description
                  file_column:
                  required: false
                - id: immap_M2nyloHRUQ
                  schema_field: carton
                  file_column:
                  required: false
                - id: immap_prklVeMgbn
                  schema_field: units_per_carton
                  file_column:
                  required: false
                - id: immap_so8jaGonyx
                  schema_field: carton_weight
                  file_column:
                  required: false
                - id: immap_rsClYtECFI
                  schema_field: cartons_per_pallet
                  file_column:
                  required: false
                - id: immap_8DR0I7fEbw
                  schema_field: image1_src
                  file_column: image1_src
                  required: false
                - id: immap_aAtNvLSUAr
                  schema_field: image2_src
                  file_column: image2_src
                  required: false
                - id: immap_QiA48cIW7A
                  schema_field: image3_src
                  file_column: image3_src
                  required: false
                - id: immap_QDA48cIW7A
                  schema_field: option1_name
                  file_column: option1_name
                  required: false
                - id: immap_8cR0I7fEbw
                  schema_field: option1_value
                  file_column: option1_value
                  required: false
                - id: immap_oqlrKdXjaP
                  schema_field: option2_name
                  file_column: option2_name
                  required: false
                - id: immap_48Olu6p4zZ
                  schema_field: option2_value
                  file_column: option2_value
                  required: false
                - id: immap_qp31JYFduR
                  schema_field: option3_name
                  file_column: option3_name
                  required: false
                - id: immap_JgaEBgznCp
                  schema_field: option3_value
                  file_column: option3_value
                  required: false
                - id: immap_tXyJwvFCuK
                  schema_field: category1
                  file_column: category1
                  required: false
                - id: immap_NJzXvxTk8u
                  schema_field: category2
                  file_column: category2
                  required: false
                - id: immap_XLbb5HTmVa
                  schema_field: category3
                  file_column: category3
                  required: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ImportCompleteMappingParams"
  "/api/v3/admin/imports/{id}/retry_failed_rows":
    patch:
      summary: Retry failed rows
      tags:
      - Imports
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Re-processes the rows that failed. The import re-enters `processing`; poll `GET /admin/imports/{id}` until it completes again. Returns 422 when the import is not `completed` or has no failed rows.

        **Required scope:** the write scope of the imported resource — `write_products` for product imports, `write_customers` for customer imports, 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 productImport = await client.imports.retryFailedRows('imp_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api patch /imports/{id}/retry_failed_rows -d '{ ... }'
      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: retry queued
          content:
            application/json:
              example:
                id: imp_gbHJdmfrXB
                number: IM1002
                rows_count: 1
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: products
                status: processing
                store_id: store_UkLWZg9DAJ
                seller_id:
                user_id: adm_UkLWZg9DAJ
                processing_errors:
                delimiter: ","
                price_list_id:
                seller_name:
                original_filename: products_import.csv
                original_byte_size: 3627
                original_file_url: "/api/v3/admin/imports/imp_gbHJdmfrXB/download"
                completed_rows_count: 0
                failed_rows_count: 1
                schema_fields:
                - name: slug
                  label: Slug
                  required: true
                - name: sku
                  label: SKU
                  required: true
                - name: name
                  label: Name
                  required: true
                - name: price
                  label: Price
                  required: true
                - name: status
                  label: Status
                  required: false
                - name: description
                  label: Description
                  required: false
                - name: meta_title
                  label: Meta Title
                  required: false
                - name: meta_description
                  label: Meta Description
                  required: false
                - name: meta_keywords
                  label: Meta Keywords
                  required: false
                - name: tags
                  label: Tags
                  required: false
                - name: compare_at_price
                  label: Compare at Price
                  required: false
                - name: currency
                  label: Currency
                  required: false
                - name: width
                  label: Width
                  required: false
                - name: height
                  label: Height
                  required: false
                - name: depth
                  label: Depth
                  required: false
                - name: dimensions_unit
                  label: Dimensions Unit
                  required: false
                - name: weight
                  label: Weight
                  required: false
                - name: weight_unit
                  label: Weight Unit
                  required: false
                - name: available_on
                  label: Available On
                  required: false
                - name: discontinue_on
                  label: Discontinue On
                  required: false
                - name: track_inventory
                  label: Track Inventory
                  required: false
                - name: inventory_count
                  label: Inventory Count
                  required: false
                - name: inventory_backorderable
                  label: Inventory Backorderable
                  required: false
                - name: stock_location
                  label: Stock Location
                  required: false
                - name: tax_category
                  label: Tax Category
                  required: false
                - name: product_type
                  label: Product Type
                  required: false
                - name: hs_code
                  label: HS Code
                  required: false
                - name: country_of_origin
                  label: Country of Origin
                  required: false
                - name: customs_description
                  label: Customs Description
                  required: false
                - name: carton
                  label: Carton
                  required: false
                - name: units_per_carton
                  label: Units per Carton
                  required: false
                - name: carton_weight
                  label: Carton Weight
                  required: false
                - name: cartons_per_pallet
                  label: Cartons per Pallet
                  required: false
                - name: image1_src
                  label: Image 1 URL
                  required: false
                - name: image2_src
                  label: Image 2 URL
                  required: false
                - name: image3_src
                  label: Image 3 URL
                  required: false
                - name: option1_name
                  label: Option 1 Name
                  required: false
                - name: option1_value
                  label: Option 1 Value
                  required: false
                - name: option2_name
                  label: Option 2 Name
                  required: false
                - name: option2_value
                  label: Option 2 Value
                  required: false
                - name: option3_name
                  label: Option 3 Name
                  required: false
                - name: option3_value
                  label: Option 3 Value
                  required: false
                - name: category1
                  label: Category 1
                  required: false
                - name: category2
                  label: Category 2
                  required: false
                - name: category3
                  label: Category 3
                  required: false
                csv_headers: []
                sample_row: {}
                mappings: []
  "/api/v3/admin/imports/{import_id}/rows":
    get:
      summary: List import rows
      tags:
      - Imports
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Paginated rows of an import — the failure report. Filter with `q[status_eq]=failed` to list only rows that could not be imported; each row carries the raw CSV `data` and its `validation_errors`.

        **Required scope:** the write scope of the imported resource — `write_products` for product imports, `write_customers` for customer imports, 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: failedRows } = await client.imports.rows.list('imp_UkLWZg9DAJ', {
            status_eq: 'failed',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /imports/{import_id}/rows -d '{"status_eq":"failed"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: import_id
        in: path
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `row_number` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `status` | One of `pending`, `processing`, `completed`, `failed` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `row_number`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: ImportRow
        sortable:
        - created_at
        - id
        - row_number
        - status
        - updated_at
      responses:
        '200':
          description: rows found
          content:
            application/json:
              example:
                data:
                - id: imrow_gbHJdmfrXB
                  row_number: 2
                  status: failed
                  validation_errors: boom
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  import_id: imp_UkLWZg9DAJ
                  item_type:
                  item_id:
                  data:
                    slug: test-product
                    name: Test Product
                    price: '10.00'
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
  "/api/v3/admin/maintenance_task_runs":
    get:
      summary: List maintenance task runs
      tags:
      - Maintenance Tasks
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The record of every maintenance task run: who started it, with which
        arguments, how far it got and how it ended.

        Runs are installation-wide rather than per store — an upgrade step
        converts every store's data — so this list is not filtered by the
        store the request is made against.


        **Required scope:** `read_maintenance_tasks` (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: runs } = await client.maintenanceTaskRuns.list({ status_eq: 'succeeded' })
      - lang: bash
        label: Spree CLI
        source: spree api get /maintenance_task_runs -d '{"status_eq":"succeeded"}'
      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[task_name_cont]
        in: query
        required: false
        description: Filter by task name (contains), e.g. `capture`
        schema:
          type: string
      - name: q[status_eq]
        in: query
        required: false
        description: Filter by status (enqueued, running, succeeded, errored, cancelled,
          …)
        schema:
          type: string
      - name: sort
        in: query
        required: false
        description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`).
        schema:
          type: string
      responses:
        '200':
          description: maintenance task runs found
          content:
            application/json:
              example:
                data:
                - id: mtr_UkLWZg9DAJ
                  status: succeeded
                  dry_run: false
                  initiated_via: dashboard
                  tick_count: 0
                  tick_total:
                  error_class:
                  error_message:
                  started_at:
                  ended_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  task_name: capture_methods
                  duration: 0.0
                  tallies: {}
                  arguments: {}
                  error_backtrace:
                  active: false
                  admin_user_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/MaintenanceTaskRun"
                  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: Start a maintenance task
      tags:
      - Maintenance Tasks
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Starts a run of a registered maintenance task and returns it. The run
        is enqueued, so poll it while `active` is true.

        `arguments` are validated by the task's own Active Model validations,
        so a bad value is rejected here rather than failing on the first
        record. `dry_run` is honored only by tasks whose `supports_dry_run` is
        true — recording a run as a preview that would in fact have written
        would misrepresent what happened.

        Only one run of a task can be in flight at a time: two would race over
        the same records and their cursors would leapfrog.


        **Required scope:** `write_maintenance_tasks` (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 run = await client.maintenanceTaskRuns.create({
            task_name: 'capture_methods',
            dry_run: true,
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /maintenance_task_runs -d '{"task_name":"capture_methods","dry_run":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
      responses:
        '201':
          description: maintenance task started
          content:
            application/json:
              example:
                id: mtr_UkLWZg9DAJ
                status: enqueued
                dry_run: true
                initiated_via: dashboard
                tick_count: 0
                tick_total:
                error_class:
                error_message:
                started_at:
                ended_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                task_name: capture_methods
                duration: 0.0
                tallies: {}
                arguments: {}
                error_backtrace:
                active: true
                admin_user_id: adm_UkLWZg9DAJ
              schema:
                "$ref": "#/components/schemas/MaintenanceTaskRun"
        '422':
          description: task is not registered
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Task name nope is not a registered maintenance task
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/MaintenanceTaskRunCreateParams"
        required: true
  "/api/v3/admin/maintenance_task_runs/{id}":
    parameters:
    - name: id
      in: path
      description: Maintenance task run ID
      required: true
      schema:
        type: string
    get:
      summary: Retrieve a maintenance task run
      tags:
      - Maintenance Tasks
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        A single run, with the progress a dashboard polls while it works.

        `progress` is `0..1` when the task could count its collection and
        `null` when it could not, in which case `tick_count` alone reports what
        has been processed. `arguments` are rendered through the task's masking
        rules, so a secret passed as a parameter is stored for reproducibility
        but never echoed back.


        **Required scope:** `read_maintenance_tasks` (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 run = await client.maintenanceTaskRuns.get('mtr_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /maintenance_task_runs/{id}
      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: maintenance task run found
          content:
            application/json:
              example:
                id: mtr_UkLWZg9DAJ
                status: running
                dry_run: false
                initiated_via: api
                tick_count: 5
                tick_total: 20
                error_class:
                error_message:
                started_at:
                ended_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                task_name: capture_methods
                duration: 0.0
                tallies: {}
                arguments: {}
                error_backtrace:
                active: true
                admin_user_id:
              schema:
                "$ref": "#/components/schemas/MaintenanceTaskRun"
        '404':
          description: maintenance task run not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Maintenance task run not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/maintenance_task_runs/{maintenance_task_run_id}/cancellation":
    parameters:
    - name: maintenance_task_run_id
      in: path
      description: Maintenance task run ID
      required: true
      schema:
        type: string
    post:
      summary: Cancel a maintenance task run
      tags:
      - Maintenance Tasks
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Asks the runner to stop for good at its next checkpoint.

        Cancelling is not a rollback — work already committed stays committed.
        What a cancelled run keeps is its cursor, so an operator can see how
        far it got. A run that is still `cancelling` because its worker has
        gone is cancelled outright by a second request.


        **Required scope:** `write_maintenance_tasks` (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 run = await client.maintenanceTaskRuns.cancel('mtr_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api post /maintenance_task_runs/{maintenance_task_run_id}/cancellation
          -d '{ ... }'
      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: maintenance task run cancelling
          content:
            application/json:
              example:
                id: mtr_UkLWZg9DAJ
                status: cancelling
                dry_run: false
                initiated_via: api
                tick_count: 0
                tick_total:
                error_class:
                error_message:
                started_at:
                ended_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                task_name: capture_methods
                duration: 0.0
                tallies: {}
                arguments: {}
                error_backtrace:
                active: true
                admin_user_id:
              schema:
                "$ref": "#/components/schemas/MaintenanceTaskRun"
        '422':
          description: maintenance task run cannot be cancelled
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: a run with status succeeded cannot be cancelled
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/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()
      - lang: bash
        label: Spree CLI
        source: spree api get /markets
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - name: page
        in: query
        required: false
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        schema:
          type: integer
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - 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
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `currency` | One of the `CurrencyCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `default_locale` | One of the `LocaleCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `currency`, `default_locale`, `id`, `name`, `position`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Market
        sortable:
        - created_at
        - currency
        - default_locale
        - id
        - name
        - position
        - updated_at
      responses:
        '200':
          description: markets found
          content:
            application/json:
              example:
                data:
                - id: mkt_UkLWZg9DAJ
                  name: United States
                  currency: USD
                  default_locale: en
                  tax_inclusive: false
                  default: true
                  country_codes:
                  - US
                  supported_locales:
                  - en
                  created_at: '2026-11-11T12:45:25.448Z'
                  updated_at: '2026-11-11T12:45:25.448Z'
                  tax_provider:
                - id: mkt_gbHJdmfrXB
                  name: EU
                  currency: USD
                  default_locale: en
                  tax_inclusive: false
                  default: false
                  country_codes:
                  - DE
                  supported_locales:
                  - en
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  tax_provider:
                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/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_codes` 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_codes: ['DE', 'FR', 'IT'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /markets -d '{"name":"Europe","currency":"EUR","default_locale":"de","supported_locales":["de","en","fr"],"tax_inclusive":true,"country_codes":["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_EfhxLZ9ck8
                name: France only
                currency: EUR
                default_locale: fr
                tax_inclusive: true
                default: false
                country_codes:
                - FR
                supported_locales:
                - en
                - fr
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                tax_provider:
              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:
                    - code: blank
                      message: can't be blank
                      specific: false
                    currency:
                    - code: blank
                      message: can't be blank
                      specific: false
                    default_locale:
                    - code: blank
                      message: can't be blank
                      specific: false
                    countries:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/MarketCreateParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /markets/{id}
      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_gbHJdmfrXB
                name: EU
                currency: USD
                default_locale: en
                tax_inclusive: false
                default: false
                country_codes:
                - DE
                supported_locales:
                - en
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                tax_provider:
              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_codes` 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_codes` 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_codes: ['DE', 'FR'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /markets/{id} -d '{"name":"European Union","tax_inclusive":true,"country_codes":["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_gbHJdmfrXB
                name: European Union
                currency: USD
                default_locale: en
                tax_inclusive: true
                default: false
                country_codes:
                - DE
                supported_locales:
                - en
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                tax_provider:
              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:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/MarketUpdateParams"
        required: true
    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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /markets/{id}
      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/{option_type_id}/custom_fields":
    get:
      summary: List option type custom fields
      tags:
      - Option Types
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the option type'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.optionTypes.customFields.list('opt_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /option_types/{option_type_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: option_type_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/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()
      - lang: bash
        label: Spree CLI
        source: spree api get /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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name and label (partial, case-insensitive).
      - name: q[search_by_name]
        in: query
        required: false
        schema:
          type: string
        description: Applies `search_by_name` to the given value.
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - 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
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `kind` | One of `dropdown`, `color_swatch`, `buttons` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `label` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `kind`, `label`, `name`, `position`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: OptionType
        sortable:
        - created_at
        - id
        - kind
        - label
        - name
        - position
        - updated_at
      responses:
        '200':
          description: option types found
          content:
            application/json:
              example:
                data:
                - id: opt_UkLWZg9DAJ
                  name: foo-size-16
                  label: Size
                  position: 1
                  kind: dropdown
                  metadata: {}
                  filterable: true
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                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',
            label: 'Color',
            option_values: [
              { name: 'red', label: 'Red' },
              { name: 'navy', label: 'Navy' },
            ],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /option_types -d '{"name":"color","label":"Color","option_values":[{"name":"red","label":"Red"},{"name":"navy","label":"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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/OptionType"
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank and Label can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
                    label:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/OptionTypeCreateParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /option_types/{id}
      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-20
                label: Size
                position: 1
                kind: dropdown
                metadata: {}
                filterable: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              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', {
            label: 'Updated Label',
            option_values: [{ name: 'red', label: 'Crimson' }],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /option_types/{id} -d '{"label":"Updated Label","option_values":[{"name":"red","label":"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-22
                label: Updated Label
                position: 1
                kind: dropdown
                metadata: {}
                filterable: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/OptionType"
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Label can't be blank
                  details:
                    label:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/OptionTypeUpdateParams"
        required: true
    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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /option_types/{id}
      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/claims":
    get:
      summary: List claims
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Every damage or missing-item claim in the store, across all orders.

        **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: claims } = await client.claims.list({
            status_eq: 'open',
            sort: '-created_at',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /claims -d '{"status_eq":"open","sort":"-created_at"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of number (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `status` | One of `open`, `approved`, `resolved`, `denied`, `canceled` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[order_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `order_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `order_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_channel_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `order_customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `order_fulfillments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_line_items_` | `additional_tax_total`, `adjustment_total`, `cost_price`, `created_at`, `discount_total`, `id`, `included_tax_total`, `non_taxable_adjustment_total`, `order_id`, `pre_tax_amount`, `price`, `quantity`, `tax_category_id`, `taxable_adjustment_total`, `updated_at`, `variant_id` |
          | `order_order_group_` | `created_at`, `currency`, `email`, `id`, `number`, `updated_at` |
          | `order_promotions_` | `code`, `created_at`, `expires_at`, `id`, `kind`, `name`, `path`, `promotion_category_id`, `starts_at`, `updated_at` |
          | `order_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `order_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_shipments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_store_` | `created_at`, `id`, `name`, `updated_at` |
          | `order_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `reason_` | `active`, `created_at`, `id`, `name`, `updated_at` |

          </Accordion>

          **Sort by:** `created_at`, `id`, `number`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Claim
        sortable:
        - created_at
        - id
        - number
        - status
        - updated_at
      responses:
        '200':
          description: claims listed
          content:
            application/json:
              example:
                data:
                - id: claim_UkLWZg9DAJ
                  number: CLM1001
                  status: open
                  resolution:
                  order_id: or_UkLWZg9DAJ
                  reason_id:
                  refund_total: '10.00'
                  approved_at:
                  resolved_at:
                  denied_at:
                  canceled_at:
                  memo: Arrived with a cracked screen
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  created_by_id:
                  created_by_type:
                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/Claim"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/orders/{order_id}/claims":
    get:
      summary: List order claims
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The damage or missing-item claims opened on one 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: claims } = await client.orders.claims.list('or_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/claims
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of number (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `status` | One of `open`, `approved`, `resolved`, `denied`, `canceled` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[order_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `order_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `order_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_channel_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `order_customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `order_fulfillments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_line_items_` | `additional_tax_total`, `adjustment_total`, `cost_price`, `created_at`, `discount_total`, `id`, `included_tax_total`, `non_taxable_adjustment_total`, `order_id`, `pre_tax_amount`, `price`, `quantity`, `tax_category_id`, `taxable_adjustment_total`, `updated_at`, `variant_id` |
          | `order_order_group_` | `created_at`, `currency`, `email`, `id`, `number`, `updated_at` |
          | `order_promotions_` | `code`, `created_at`, `expires_at`, `id`, `kind`, `name`, `path`, `promotion_category_id`, `starts_at`, `updated_at` |
          | `order_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `order_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_shipments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_store_` | `created_at`, `id`, `name`, `updated_at` |
          | `order_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `reason_` | `active`, `created_at`, `id`, `name`, `updated_at` |

          </Accordion>

          **Sort by:** `created_at`, `id`, `number`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Claim
        sortable:
        - created_at
        - id
        - number
        - status
        - updated_at
      responses:
        '200':
          description: claims listed
          content:
            application/json:
              example:
                data:
                - id: claim_UkLWZg9DAJ
                  number: CLM1001
                  status: open
                  resolution:
                  order_id: or_UkLWZg9DAJ
                  reason_id:
                  refund_total: '10.00'
                  approved_at:
                  resolved_at:
                  denied_at:
                  canceled_at:
                  memo: Arrived with a cracked screen
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  created_by_id:
                  created_by_type:
                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/Claim"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Create a claim
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Opens a damage or missing-item claim on a completed order. Each item says how it should be made right: money back, a replacement, or both.

        **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',
          })

          // The customer keeps the goods: nothing comes back, so no return is opened.
          const claim = await client.orders.claims.create('or_UkLWZg9DAJ', {
            reason_id: 'clr_UkLWZg9DAJ',
            memo: 'Arrived with a cracked lid',
            items: [
              {
                line_item_id: 'li_UkLWZg9DAJ',
                quantity: 1,
                description: 'Lid cracked in transit',
                send_replacement: true,
              },
            ],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{order_id}/claims -d '{"reason_id":"clr_UkLWZg9DAJ","memo":"Arrived
          with a cracked lid","items":[{"line_item_id":"li_UkLWZg9DAJ","quantity":1,"description":"Lid
          cracked in transit","send_replacement":true}]}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      responses:
        '201':
          description: claim opened
          content:
            application/json:
              example:
                id: claim_gbHJdmfrXB
                number: CLM1002
                status: open
                resolution:
                order_id: or_gbHJdmfrXB
                reason_id:
                refund_total: '10.00'
                approved_at:
                resolved_at:
                denied_at:
                canceled_at:
                memo: Arrived cracked
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                created_by_id: adm_UkLWZg9DAJ
                created_by_type: admin_user
              schema:
                "$ref": "#/components/schemas/Claim"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ClaimCreateParams"
        required: true
  "/api/v3/admin/orders/{order_id}/claims/{id}":
    patch:
      summary: Update a claim
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Edits the reason, memo or metadata of a claim. Its status moves only through the approve, resolve, deny and cancel actions.

        **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 claim = await client.orders.claims.update('or_UkLWZg9DAJ', 'claim_UkLWZg9DAJ', {
            memo: 'Photos received from the customer',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/claims/{id} -d '{"memo":"Photos
          received from the customer"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Claim prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: claim updated
          content:
            application/json:
              example:
                id: claim_UkLWZg9DAJ
                number: CLM1001
                status: open
                resolution:
                order_id: or_UkLWZg9DAJ
                reason_id: clr_UkLWZg9DAJ
                refund_total: '10.00'
                approved_at:
                resolved_at:
                denied_at:
                canceled_at:
                memo: Customer sent photos
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                created_by_id:
                created_by_type:
              schema:
                "$ref": "#/components/schemas/Claim"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ClaimUpdateParams"
        required: true
  "/api/v3/admin/orders/{order_id}/claims/{id}/approve":
    patch:
      summary: Approve a claim
      tags:
      - Orders
      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 claim = await client.orders.claims.approve('or_UkLWZg9DAJ', 'claim_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/claims/{id}/approve -d '{ ... }'
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Accepts an open claim, the step before resolving it with a refund, a replacement or both. Only an open claim can be approved; deny it to turn it down.

        **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
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Claim prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: claim approved
          content:
            application/json:
              example:
                id: claim_UkLWZg9DAJ
                number: CLM1001
                status: approved
                resolution:
                order_id: or_UkLWZg9DAJ
                reason_id:
                refund_total: '10.00'
                approved_at: '2026-01-15T12:00:00Z'
                resolved_at:
                denied_at:
                canceled_at:
                memo: Arrived with a cracked screen
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                created_by_id: adm_UkLWZg9DAJ
                created_by_type: admin_user
              schema:
                "$ref": "#/components/schemas/Claim"
  "/api/v3/admin/orders/{order_id}/claims/{id}/resolve":
    patch:
      summary: Resolve a claim
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Settles an approved claim with money back, a replacement shipment, or both.

        **Required scope:** `write_orders`, plus `write_refunds` for a resolution that 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 claim = await client.orders.claims.resolve('or_UkLWZg9DAJ', 'claim_UkLWZg9DAJ', {
            resolution: 'refund_and_replacement',
            refund_method: 'original_payment',
            amount: '5.00',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/claims/{id}/resolve -d '{"resolution":"refund_and_replacement","refund_method":"original_payment","amount":"5.00"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Claim prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: claim resolved
          content:
            application/json:
              example:
                id: claim_UkLWZg9DAJ
                number: CLM1001
                status: resolved
                resolution: refund
                order_id: or_UkLWZg9DAJ
                reason_id:
                refund_total: '10.00'
                approved_at: '2026-01-15T12:00:00Z'
                resolved_at: '2026-01-15T12:00:00Z'
                denied_at:
                canceled_at:
                memo: Arrived with a cracked screen
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                created_by_id:
                created_by_type:
              schema:
                "$ref": "#/components/schemas/Claim"
        '422':
          description: unknown resolution
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: Invalid resolution
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ClaimResolveParams"
        required: true
  "/api/v3/admin/orders/{order_id}/claims/{id}/deny":
    patch:
      summary: Deny a claim
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Turns down an open claim, recording why for the customer.

        **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 claim = await client.orders.claims.deny('or_UkLWZg9DAJ', 'claim_UkLWZg9DAJ', {
            reason: 'Damage is not covered after 30 days',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/claims/{id}/deny -d '{"reason":"Damage
          is not covered after 30 days"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Claim prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: claim denied
          content:
            application/json:
              example:
                id: claim_UkLWZg9DAJ
                number: CLM1001
                status: denied
                resolution:
                order_id: or_UkLWZg9DAJ
                reason_id:
                refund_total: '10.00'
                approved_at:
                resolved_at:
                denied_at: '2026-01-15T12:00:00Z'
                canceled_at:
                memo: |-
                  Arrived with a cracked screen
                  Outside warranty
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                created_by_id:
                created_by_type:
              schema:
                "$ref": "#/components/schemas/Claim"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ClaimDenyParams"
  "/api/v3/admin/orders/{order_id}/claims/{id}/cancel":
    patch:
      summary: Cancel a claim
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Withdraws a claim that has not been resolved.

        **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 claim = await client.orders.claims.cancel('or_UkLWZg9DAJ', 'claim_UkLWZg9DAJ', {
            reason: 'Opened by mistake',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/claims/{id}/cancel -d '{"reason":"Opened
          by mistake"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Claim prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: claim canceled
          content:
            application/json:
              example:
                id: claim_UkLWZg9DAJ
                number: CLM1001
                status: canceled
                resolution:
                order_id: or_UkLWZg9DAJ
                reason_id:
                refund_total: '10.00'
                approved_at:
                resolved_at:
                denied_at:
                canceled_at: '2026-01-15T12:00:00Z'
                memo: |-
                  Arrived with a cracked screen
                  Customer found the missing item
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                created_by_id:
                created_by_type:
              schema:
                "$ref": "#/components/schemas/Claim"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ClaimCancelParams"
  "/api/v3/admin/orders/{order_id}/custom_fields":
    get:
      summary: List order custom fields
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the order's custom field values.

        **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: customFields } = await client.orders.customFields.list('or_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/digital_links":
    get:
      summary: List digital links
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the download links issued for digital products bought in this store, newest first.

        **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: digitalLinks } = await client.digitalLinks.list({
            sort: '-created_at',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /digital_links -d '{"sort":"-created_at"}'
      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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: DigitalLink
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: digital links found
          content:
            application/json:
              example:
                data:
                - id: dl_UkLWZg9DAJ
                  access_counter: 0
                  filename: thinking-cat.jpg
                  content_type: image/jpeg
                  download_url: "/api/v3/store/digital_links/Sh7B5YVQvB8N7t2mhgUnL9Lv"
                  expires_at: '2026-01-22T12:00:00Z'
                  authorizable: true
                  expired: false
                  access_limit_exceeded: false
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                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/DigitalLink"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/digital_links/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Digital link ID
      schema:
        type: string
    get:
      summary: Get a digital link
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a single download link with its download count and expiry.

        **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 digitalLink = await client.digitalLinks.retrieve('dl_xxx')
      - lang: bash
        label: Spree CLI
        source: spree api get /digital_links/{id}
      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: digital link found
          content:
            application/json:
              example:
                id: dl_UkLWZg9DAJ
                access_counter: 0
                filename: thinking-cat.jpg
                content_type: image/jpeg
                download_url: "/api/v3/store/digital_links/ks9F16gjTLQPCzwFDpj2ifrJ"
                expires_at: '2026-01-22T12:00:00Z'
                authorizable: true
                expired: false
                access_limit_exceeded: false
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/DigitalLink"
        '404':
          description: digital link not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Digital link not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/digital_links/{id}/reset":
    parameters:
    - name: id
      in: path
      required: true
      description: Digital link ID
      schema:
        type: string
    patch:
      summary: Reset a digital link
      tags:
      - Orders
      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 digitalLink = await client.digitalLinks.reset('dl_xxx')
      - lang: bash
        label: Spree CLI
        source: spree api patch /digital_links/{id}/reset -d '{ ... }'
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Gives the customer their full download allowance back and restarts the
        link's expiry clock. Use it when a download failed, or the file was
        replaced after the customer had used up their attempts.


        **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:
        '200':
          description: digital link reset
          content:
            application/json:
              example:
                id: dl_UkLWZg9DAJ
                access_counter: 0
                filename: thinking-cat.jpg
                content_type: image/jpeg
                download_url: "/api/v3/store/digital_links/tPqch4JvZidezkNn2YoqxDLc"
                expires_at: '2026-01-22T12:00:00Z'
                authorizable: true
                expired: false
                access_limit_exceeded: false
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/DigitalLink"
  "/api/v3/admin/exchanges":
    get:
      summary: List exchanges
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Every exchange in the store, across all orders.

        **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: exchanges } = await client.exchanges.list({
            status_eq: 'received',
            sort: '-created_at',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /exchanges -d '{"status_eq":"received","sort":"-created_at"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of number (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `status` | One of `requested`, `approved`, `received`, `fulfilled`, `canceled` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[order_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `order_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `order_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_channel_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `order_customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `order_fulfillments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_line_items_` | `additional_tax_total`, `adjustment_total`, `cost_price`, `created_at`, `discount_total`, `id`, `included_tax_total`, `non_taxable_adjustment_total`, `order_id`, `pre_tax_amount`, `price`, `quantity`, `tax_category_id`, `taxable_adjustment_total`, `updated_at`, `variant_id` |
          | `order_order_group_` | `created_at`, `currency`, `email`, `id`, `number`, `updated_at` |
          | `order_promotions_` | `code`, `created_at`, `expires_at`, `id`, `kind`, `name`, `path`, `promotion_category_id`, `starts_at`, `updated_at` |
          | `order_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `order_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_shipments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_store_` | `created_at`, `id`, `name`, `updated_at` |
          | `order_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `reason_` | `active`, `created_at`, `id`, `name`, `updated_at` |

          </Accordion>

          **Sort by:** `created_at`, `id`, `number`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Exchange
        sortable:
        - created_at
        - id
        - number
        - status
        - updated_at
      responses:
        '200':
          description: exchanges listed
          content:
            application/json:
              example:
                data:
                - id: exch_UkLWZg9DAJ
                  number: EX1001
                  status: requested
                  order_id: or_UkLWZg9DAJ
                  reason_id:
                  price_difference: '9.99'
                  approved_at:
                  received_at:
                  fulfilled_at:
                  canceled_at:
                  memo: Wrong size
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  stock_location_id: sloc_UkLWZg9DAJ
                  created_by_id:
                  created_by_type:
                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/Exchange"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/orders/{order_id}/exchanges":
    get:
      summary: List order exchanges
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The exchanges opened on one 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: exchanges } = await client.orders.exchanges.list('or_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/exchanges
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of number (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `status` | One of `requested`, `approved`, `received`, `fulfilled`, `canceled` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[order_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `order_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `order_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_channel_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `order_customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `order_fulfillments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_line_items_` | `additional_tax_total`, `adjustment_total`, `cost_price`, `created_at`, `discount_total`, `id`, `included_tax_total`, `non_taxable_adjustment_total`, `order_id`, `pre_tax_amount`, `price`, `quantity`, `tax_category_id`, `taxable_adjustment_total`, `updated_at`, `variant_id` |
          | `order_order_group_` | `created_at`, `currency`, `email`, `id`, `number`, `updated_at` |
          | `order_promotions_` | `code`, `created_at`, `expires_at`, `id`, `kind`, `name`, `path`, `promotion_category_id`, `starts_at`, `updated_at` |
          | `order_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `order_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_shipments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_store_` | `created_at`, `id`, `name`, `updated_at` |
          | `order_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `reason_` | `active`, `created_at`, `id`, `name`, `updated_at` |

          </Accordion>

          **Sort by:** `created_at`, `id`, `number`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Exchange
        sortable:
        - created_at
        - id
        - number
        - status
        - updated_at
      responses:
        '200':
          description: exchanges listed
          content:
            application/json:
              example:
                data:
                - id: exch_UkLWZg9DAJ
                  number: EX1001
                  status: requested
                  order_id: or_UkLWZg9DAJ
                  reason_id:
                  price_difference: '9.99'
                  approved_at:
                  received_at:
                  fulfilled_at:
                  canceled_at:
                  memo: Wrong size
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  stock_location_id: sloc_UkLWZg9DAJ
                  created_by_id:
                  created_by_type:
                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/Exchange"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Create an exchange
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Opens an exchange on a completed order: items coming back, and the variant that goes out in place of each.

        **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 exchange = await client.orders.exchanges.create('or_UkLWZg9DAJ', {
            reason_id: 'rar_UkLWZg9DAJ',
            stock_location_id: 'sloc_UkLWZg9DAJ',
            items: [
              { fulfillment_item_id: 'fi_UkLWZg9DAJ', new_variant_id: 'variant_k5nR8xLq', quantity: 1 },
            ],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{order_id}/exchanges -d '{"reason_id":"rar_UkLWZg9DAJ","stock_location_id":"sloc_UkLWZg9DAJ","items":[{"fulfillment_item_id":"fi_UkLWZg9DAJ","new_variant_id":"variant_k5nR8xLq","quantity":1}]}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      responses:
        '201':
          description: exchange opened
          content:
            application/json:
              example:
                id: exch_gbHJdmfrXB
                number: EX1002
                status: requested
                order_id: or_gbHJdmfrXB
                reason_id:
                price_difference: '9.99'
                approved_at:
                received_at:
                fulfilled_at:
                canceled_at:
                memo: Wrong size
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                stock_location_id: sloc_UkLWZg9DAJ
                created_by_id: adm_UkLWZg9DAJ
                created_by_type: admin_user
              schema:
                "$ref": "#/components/schemas/Exchange"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ExchangeCreateParams"
        required: true
  "/api/v3/admin/orders/{order_id}/exchanges/{id}":
    patch:
      summary: Update an exchange
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Edits the warehouse, reason, memo or metadata of an exchange. Its status moves only through the approve, receive, fulfill and cancel actions.

        **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 exchange = await client.orders.exchanges.update('or_UkLWZg9DAJ', 'exch_UkLWZg9DAJ', {
            memo: 'Customer prefers the larger size',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/exchanges/{id} -d '{"memo":"Customer
          prefers the larger size"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Exchange prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: exchange updated
          content:
            application/json:
              example:
                id: exch_UkLWZg9DAJ
                number: EX1001
                status: requested
                order_id: or_UkLWZg9DAJ
                reason_id: rar_UkLWZg9DAJ
                price_difference: '9.99'
                approved_at:
                received_at:
                fulfilled_at:
                canceled_at:
                memo: Customer wants a larger size
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                stock_location_id: sloc_UkLWZg9DAJ
                created_by_id:
                created_by_type:
              schema:
                "$ref": "#/components/schemas/Exchange"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ExchangeUpdateParams"
        required: true
  "/api/v3/admin/orders/{order_id}/exchanges/{id}/approve":
    patch:
      summary: Approve an exchange
      tags:
      - Orders
      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 exchange = await client.orders.exchanges.approve('or_UkLWZg9DAJ', 'exch_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/exchanges/{id}/approve -d '{ ...
          }'
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Accepts a requested exchange so the customer can send the goods back for their replacement. Only a requested exchange can be approved; receive it once the goods arrive.

        **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
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Exchange prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: exchange approved
          content:
            application/json:
              example:
                id: exch_UkLWZg9DAJ
                number: EX1001
                status: approved
                order_id: or_UkLWZg9DAJ
                reason_id:
                price_difference: '9.99'
                approved_at: '2026-01-15T12:00:00Z'
                received_at:
                fulfilled_at:
                canceled_at:
                memo: Wrong size
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                stock_location_id: sloc_UkLWZg9DAJ
                created_by_id: adm_UkLWZg9DAJ
                created_by_type: admin_user
              schema:
                "$ref": "#/components/schemas/Exchange"
        '422':
          description: the exchange is not requested
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: Not requested
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/orders/{order_id}/exchanges/{id}/receive":
    patch:
      summary: Receive an exchange
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Records the goods that came back on an approved exchange. Omit `items` to receive everything as requested and resellable.

        **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',
          })

          // Omit `items` to receive everything as requested and resellable.
          const exchange = await client.orders.exchanges.receive('or_UkLWZg9DAJ', 'exch_UkLWZg9DAJ', {
            items: [{ exchange_line_item_id: 'eli_UkLWZg9DAJ', quantity: 1, resellable: false }],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/exchanges/{id}/receive -d '{"items":[{"exchange_line_item_id":"eli_UkLWZg9DAJ","quantity":1,"resellable":false}]}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Exchange prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: exchange received
          content:
            application/json:
              example:
                id: exch_UkLWZg9DAJ
                number: EX1001
                status: received
                order_id: or_UkLWZg9DAJ
                reason_id:
                price_difference: '9.99'
                approved_at: '2026-01-15T12:00:00Z'
                received_at: '2026-01-15T12:00:00Z'
                fulfilled_at:
                canceled_at:
                memo: Wrong size
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                stock_location_id: sloc_UkLWZg9DAJ
                created_by_id:
                created_by_type:
              schema:
                "$ref": "#/components/schemas/Exchange"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ExchangeReceiveParams"
  "/api/v3/admin/orders/{order_id}/exchanges/{id}/fulfill":
    patch:
      summary: Fulfill an exchange
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Ships the replacements for a received exchange and settles any price difference.

        **Required scope:** `write_orders` and `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 exchange = await client.orders.exchanges.fulfill('or_UkLWZg9DAJ', 'exch_UkLWZg9DAJ', {
            refund_method: 'store_credit',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/exchanges/{id}/fulfill -d '{"refund_method":"store_credit"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Exchange prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: exchange fulfilled
          content:
            application/json:
              example:
                id: exch_UkLWZg9DAJ
                number: EX1001
                status: fulfilled
                order_id: or_UkLWZg9DAJ
                reason_id:
                price_difference: '9.99'
                approved_at: '2026-01-14T12:00:00Z'
                received_at: '2026-01-15T12:00:00Z'
                fulfilled_at: '2026-01-15T12:00:00Z'
                canceled_at:
                memo: Wrong size
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                stock_location_id: sloc_UkLWZg9DAJ
                created_by_id:
                created_by_type:
              schema:
                "$ref": "#/components/schemas/Exchange"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ExchangeFulfillParams"
  "/api/v3/admin/orders/{order_id}/exchanges/{id}/cancel":
    patch:
      summary: Cancel an exchange
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Withdraws an exchange whose goods have not been received.

        **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 exchange = await client.orders.exchanges.cancel('or_UkLWZg9DAJ', 'exch_UkLWZg9DAJ', {
            reason: 'Customer kept the original item',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/exchanges/{id}/cancel -d '{"reason":"Customer
          kept the original item"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Exchange prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: exchange canceled
          content:
            application/json:
              example:
                id: exch_UkLWZg9DAJ
                number: EX1001
                status: canceled
                order_id: or_UkLWZg9DAJ
                reason_id:
                price_difference: '9.99'
                approved_at:
                received_at:
                fulfilled_at:
                canceled_at: '2026-01-15T12:00:00Z'
                memo: |-
                  Wrong size
                  Customer kept the original
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                stock_location_id: sloc_UkLWZg9DAJ
                created_by_id:
                created_by_type:
              schema:
                "$ref": "#/components/schemas/Exchange"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ExchangeCancelParams"
  "/api/v3/admin/orders/{order_id}/tax_lines":
    get:
      summary: List tax lines
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Typed tax rows on the order. Read-only — written exclusively by the tax provider.

        **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: taxLines } = await client.orders.taxLines.list('or_abc123')
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/tax_lines
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[provider_id_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `country_code` | One of the `CountryCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `included` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `provider_id` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `state_code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `taxability_reason` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `country_code`, `created_at`, `id`, `included`, `provider_id`, `state_code`, `taxability_reason`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: TaxLine
        sortable:
        - country_code
        - created_at
        - id
        - included
        - provider_id
        - state_code
        - taxability_reason
        - updated_at
      responses:
        '200':
          description: tax lines found
          content:
            application/json:
              example:
                data:
                - id: tl_UkLWZg9DAJ
                  label: VAT 15%
                  included: false
                  credit: false
                  rate: '0.15'
                  tax_rate_id:
                  line_item_id: li_UkLWZg9DAJ
                  fulfillment_id:
                  fee_id:
                  return_line_item_id:
                  claim_line_item_id:
                  exchange_line_item_id:
                  amount: '1.50'
                  provider_id: internal
                  metadata: {}
                  taxability_reason:
                  country_code:
                  state_code:
                  data: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  original_tax_line_id:
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
  "/api/v3/admin/orders/{order_id}/discounts":
    get:
      summary: List discounts
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Typed discount rows (promotion-sourced and manual) on the 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: discounts } = await client.orders.discounts.list('or_abc123')
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/discounts
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Discount
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: discounts found
          content:
            application/json:
              example:
                data:
                - id: disc_UkLWZg9DAJ
                  label: Loyalty
                  kind: manual
                  code:
                  value_type:
                  value:
                  promotion_id:
                  line_item_id: li_UkLWZg9DAJ
                  fulfillment_id:
                  amount: "-2.00"
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Create manual discount
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Creates a manual discount. With line_item_id a single row is created; without it the amount is distributed across line items (largest remainder). This is the sanctioned post-placement discount path and works on completed orders.

        **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',
          })

          // Line-item discount; omit line_item_id to distribute across the order.
          const { data: discounts } = await client.orders.discounts.create('or_abc123', {
            label: 'Customer appeasement',
            value: '10',
            value_type: 'flat',
            line_item_id: 'item_abc123',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{order_id}/discounts -d '{"label":"Customer
          appeasement","value":"10","value_type":"flat","line_item_id":"item_abc123"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      responses:
        '201':
          description: discount created
          content:
            application/json:
              example:
                data:
                - id: disc_UkLWZg9DAJ
                  label: Appeasement
                  kind: manual
                  code:
                  value_type: flat
                  value: '3.00'
                  promotion_id:
                  line_item_id: li_UkLWZg9DAJ
                  fulfillment_id:
                  amount: "-3.00"
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
        '422':
          description: invalid discount
          content:
            application/json:
              example:
                error:
                  code: invalid_money_format
                  message: value must be a decimal string like "19.99"
                  details:
                    value:
                    - must be a decimal string like "19.99"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DiscountCreateParams"
        required: true
  "/api/v3/admin/orders/{order_id}/discounts/{id}":
    patch:
      summary: Update manual discount
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Edits the label or amount of a manual discount and re-sums the order totals. Promotion-sourced rows are owned by recalculation and respond 422.

        **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 discount = await client.orders.discounts.update('or_UkLWZg9DAJ', 'disc_UkLWZg9DAJ', {
            label: 'Customer appeasement',
            amount: '15.00',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/discounts/{id} -d '{"label":"Customer
          appeasement","amount":"15.00"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Discount prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: discount updated
          content:
            application/json:
              example:
                id: disc_UkLWZg9DAJ
                label: Loyalty reward
                kind: manual
                code:
                value_type:
                value:
                promotion_id:
                line_item_id: li_UkLWZg9DAJ
                fulfillment_id:
                amount: "-5.00"
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DiscountUpdateParams"
        required: true
  "/api/v3/admin/orders/{order_id}/fees":
    get:
      summary: List fees
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the order's fees, such as surcharges, handling and gift wrap, on the whole order or on one item or delivery.

        **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: fees } = await client.orders.fees.list('or_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/fees
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Fee
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: fees found
          content:
            application/json:
              example:
                data:
                - id: fee_UkLWZg9DAJ
                  label: Gift wrap
                  kind: gift_wrap
                  line_item_id:
                  fulfillment_id:
                  amount: '4.00'
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                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/Fee"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Create fee
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Creates a fee (surcharge, handling, gift wrap, COD, payment fee). Order-level when no target is given. Works on completed orders.

        **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 fee = await client.orders.fees.create('or_abc123', {
            label: 'Gift wrap',
            amount: '4.00',
            kind: 'gift_wrap',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{order_id}/fees -d '{"label":"Gift wrap","amount":"4.00","kind":"gift_wrap"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      responses:
        '201':
          description: fee created
          content:
            application/json:
              example:
                id: fee_UkLWZg9DAJ
                label: Gift wrap
                kind: gift_wrap
                line_item_id:
                fulfillment_id:
                amount: '4.00'
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
        '422':
          description: invalid fee
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Kind is not included in the list
                  details:
                    kind:
                    - value: nonsense
                      code: inclusion
                      message: is not included in the list
                      specific: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/FeeCreateParams"
        required: true
  "/api/v3/admin/orders/{order_id}/fees/{id}":
    patch:
      summary: Update fee
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Edits the label, amount or kind of a fee and re-sums the order totals. Works on completed orders.

        **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 fee = await client.orders.fees.update('or_UkLWZg9DAJ', 'fee_UkLWZg9DAJ', {
            label: 'Gift wrap',
            amount: '5.00',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/fees/{id} -d '{"label":"Gift wrap","amount":"5.00"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Fee prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: fee updated
          content:
            application/json:
              example:
                id: fee_UkLWZg9DAJ
                label: Handling
                kind: handling
                line_item_id:
                fulfillment_id:
                amount: '8.00'
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/Fee"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/FeeUpdateParams"
        required: true
  "/api/v3/admin/order_groups":
    get:
      summary: List order groups
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns checkouts split into one order per seller, grouping the orders placed together.

        **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: orderGroups } = await client.orderGroups.list({
            email_cont: 'jane@example.com',
            sort: '-created_at',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /order_groups -d '{"email_cont":"jane@example.com","sort":"-created_at"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `currency` | One of the `CurrencyCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `email` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[customer_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `customer_addresses_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customer_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customer_customer_groups_` | `created_at`, `id`, `name`, `updated_at` |
          | `customer_orders_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `customer_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customer_spree_roles_` | `created_at`, `id`, `name`, `updated_at` |
          | `customer_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `orders_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `orders_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `orders_channel_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `orders_customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `orders_fulfillments_` | `created_at`, `id`, `number`, `updated_at` |
          | `orders_line_items_` | `additional_tax_total`, `adjustment_total`, `cost_price`, `created_at`, `discount_total`, `id`, `included_tax_total`, `non_taxable_adjustment_total`, `order_id`, `pre_tax_amount`, `price`, `quantity`, `tax_category_id`, `taxable_adjustment_total`, `updated_at`, `variant_id` |
          | `orders_promotions_` | `code`, `created_at`, `expires_at`, `id`, `kind`, `name`, `path`, `promotion_category_id`, `starts_at`, `updated_at` |
          | `orders_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `orders_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `orders_shipments_` | `created_at`, `id`, `number`, `updated_at` |
          | `orders_store_` | `created_at`, `id`, `name`, `updated_at` |
          | `orders_tags_` | `created_at`, `id`, `name`, `updated_at` |

          </Accordion>

          **Sort by:** `created_at`, `currency`, `email`, `id`, `number`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: OrderGroup
        sortable:
        - created_at
        - currency
        - email
        - id
        - number
        - updated_at
      responses:
        '200':
          description: order groups found
          content:
            application/json:
              example:
                data:
                - id: ogrp_UkLWZg9DAJ
                  number: R1001
                  email: sylvie@rau.info
                  currency: USD
                  item_total: '0.00'
                  discount_total: '0.00'
                  tax_total: '0.00'
                  included_tax_total: '0.00'
                  additional_tax_total: '0.00'
                  delivery_total: '0.00'
                  fee_total: '0.00'
                  gift_card_total: '0.00'
                  store_credit_total: '0.00'
                  total: '0.00'
                  amount_due: '0.00'
                  covered_by_store_credit: false
                  payments: []
                  fulfillment_status:
                  payment_status:
                  completed_at: '2026-01-15T12:00:00.000Z'
                  billing_address:
                  shipping_address:
                  orders: []
                  customer_id: cust_UkLWZg9DAJ
                  cart_id:
                  seller_count: 0
                  includes_first_party: false
                  confirmation_delivered: false
                  store_owner_notification_delivered: false
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                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/OrderGroup"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/orders/{order_id}/discount_codes":
    post:
      summary: Apply a discount code
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Applies a discount code to a draft order and returns the order. A real code the order does not yet qualify for is kept and applies once it does. Completed orders refuse codes; change their discounts through manual discounts instead.

        **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.discountCodes.create('or_UkLWZg9DAJ', {
            code: 'SUMMER20',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{order_id}/discount_codes -d '{"code":"SUMMER20"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      responses:
        '201':
          description: discount code applied
          content:
            application/json:
              example:
                id: or_UkLWZg9DAJ
                market_id: mkt_UkLWZg9DAJ
                withdrawal_period_ends_at:
                within_withdrawal_period: false
                shipping_eq_billing_address: false
                cart_id:
                channel_id: ch_UkLWZg9DAJ
                company_id:
                company_name:
                po_document_filename:
                po_document_byte_size:
                number: R1001
                email: larue@gerlachoga.biz
                customer_note:
                po_number:
                currency: USD
                locale: en
                total_quantity: 1
                coupon_code: save5
                fulfillment_status:
                payment_status:
                completed_at:
                item_total: '50.00'
                discount_total: "-5.00"
                tax_total: '0.00'
                included_tax_total: '0.00'
                additional_tax_total: '0.00'
                delivery_total: '100.00'
                fee_total: '0.00'
                gift_card_total: '0.00'
                store_credit_total: '0.00'
                total: '145.00'
                amount_due: '145.00'
                covered_by_store_credit: false
                adjustment_total: "-5.00"
                gift_card:
                market:
                  id: mkt_UkLWZg9DAJ
                  name: United States
                  currency: USD
                  default_locale: en
                  tax_inclusive: false
                  default: true
                  country_codes:
                  - US
                  supported_locales:
                  - en
                  created_at: '2026-11-11T12:45:25.448Z'
                  updated_at: '2026-11-11T12:45:25.448Z'
                  tax_provider:
                external_references: {}
                status: draft
                last_ip_address:
                considered_risky: false
                confirmation_delivered: false
                store_owner_notification_delivered:
                metadata: {}
                cancel_note:
                canceled_at:
                approved_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                payment_total: '0.00'
                commission_amount_total: '0.00'
                commission_tax_total: '0.00'
                commission_total: '0.00'
                preferred_stock_location_id:
                po_document_url:
                seller_id:
                order_group_id:
                tags: []
                internal_note:
                internal_note_html:
                approver_id:
                approver_type:
                canceler_id:
                canceler_type:
                created_by_id:
                created_by_type:
                cancel_reason_id:
                cancel_reason_name:
                customer_id: cust_UkLWZg9DAJ
                freight_summary:
        '422':
          description: unknown discount code
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: The coupon code you entered doesn't exist. Please try again.
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DiscountCodeApplyParams"
        required: true
  "/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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{order_id}/gift_cards -d '{"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: "************2F41"
                status: active
                currency: USD
                amount: '10.00'
                amount_used: '10.00'
                amount_authorized: '0.00'
                amount_remaining: '0.00'
                expires_at:
                redeemed_at:
                expired: false
                active: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                customer_id:
                created_by_id:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/GiftCardApplyParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /orders/{order_id}/gift_cards/{id}
      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')
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/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: 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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[additional_tax_total_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `additional_tax_total` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `adjustment_total` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `cost_price` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `discount_total` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `included_tax_total` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `non_taxable_adjustment_total` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `order_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `pre_tax_amount` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `price` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `quantity` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `tax_category_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `taxable_adjustment_total` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `variant_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[order_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `order_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `order_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_channel_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `order_customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `order_fulfillments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_order_group_` | `created_at`, `currency`, `email`, `id`, `number`, `updated_at` |
          | `order_promotions_` | `code`, `created_at`, `expires_at`, `id`, `kind`, `name`, `path`, `promotion_category_id`, `starts_at`, `updated_at` |
          | `order_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `order_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_shipments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_store_` | `created_at`, `id`, `name`, `updated_at` |
          | `order_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |
          | `variant_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `variant_option_values_` | `created_at`, `id`, `label`, `name`, `position`, `updated_at` |
          | `variant_prices_` | `amount`, `compare_at_amount`, `created_at`, `currency`, `id`, `min_quantity`, `price_list_id`, `updated_at`, `variant_id` |
          | `variant_product_` | `available_on`, `created_at`, `description`, `discontinue_on`, `id`, `name`, `price`, `seller_id`, `slug`, `status`, `updated_at` |
          | `variant_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `variant_tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |

          </Accordion>

          **Sort by:** `additional_tax_total`, `adjustment_total`, `cost_price`, `created_at`, `discount_total`, `id`, `included_tax_total`, `non_taxable_adjustment_total`, `order_id`, `pre_tax_amount`, `price`, `quantity`, `tax_category_id`, `taxable_adjustment_total`, `updated_at`, `variant_id`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: LineItem
        sortable:
        - additional_tax_total
        - adjustment_total
        - cost_price
        - created_at
        - discount_total
        - id
        - included_tax_total
        - non_taxable_adjustment_total
        - order_id
        - pre_tax_amount
        - price
        - quantity
        - tax_category_id
        - taxable_adjustment_total
        - updated_at
        - variant_id
      responses:
        '200':
          description: items found
          content:
            application/json:
              example:
                data:
                - id: li_UkLWZg9DAJ
                  variant_id: variant_gbHJdmfrXB
                  seller_id:
                  preorder: false
                  preorder_ships_at:
                  quantity: 2
                  currency: USD
                  name: Product 849180
                  slug: product-849180
                  options_text: 'Size: S'
                  price: '10.00'
                  total: '20.00'
                  adjustment_total: '0.00'
                  additional_tax_total: '0.00'
                  included_tax_total: '0.00'
                  discount_total: '0.00'
                  pre_tax_amount: '20.00'
                  discounted_amount: '20.00'
                  compare_at_amount:
                  thumbnail_url:
                  option_values:
                  - id: optval_UkLWZg9DAJ
                    option_type_id: opt_UkLWZg9DAJ
                    name: size-15
                    label: S
                    position: 1
                    color_code:
                    option_type_name: foo-size-25
                    option_type_label: Size
                    image_url:
                    metadata: {}
                    created_at: '2026-01-15T12:00:00.000Z'
                    updated_at: '2026-01-15T12:00:00.000Z'
                  digital_links: []
                  external_references: {}
                  metadata: {}
                  price_source:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  catalog_price: '19.99'
                  price_list_id:
                  price_list_name:
                  catalog_id:
                  catalog_name:
                  cost_price: '17.00'
                  tax_category_id: taxcat_UkLWZg9DAJ
                  product_id: prod_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,
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{order_id}/items -d '{"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
                seller_id:
                preorder: false
                preorder_ships_at:
                quantity: 3
                currency: USD
                name: Product 8699
                slug: product-8699
                options_text: 'Size: S'
                price: '19.99'
                total: '59.97'
                adjustment_total: '0.00'
                additional_tax_total: '0.00'
                included_tax_total: '0.00'
                discount_total: '0.00'
                pre_tax_amount: '59.97'
                discounted_amount: '59.97'
                compare_at_amount:
                thumbnail_url:
                option_values:
                - id: optval_gbHJdmfrXB
                  option_type_id: opt_gbHJdmfrXB
                  name: size-17
                  label: S
                  position: 1
                  color_code:
                  option_type_name: foo-size-27
                  option_type_label: Size
                  image_url:
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                digital_links: []
                external_references: {}
                metadata: {}
                price_source:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                catalog_price: '19.99'
                price_list_id:
                price_list_name:
                catalog_id:
                catalog_name:
                cost_price: '17.00'
                tax_category_id: taxcat_UkLWZg9DAJ
                product_id: prod_gbHJdmfrXB
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/LineItemCreateParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/items/{id}
      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
                seller_id:
                preorder: false
                preorder_ships_at:
                quantity: 2
                currency: USD
                name: Product 872714
                slug: product-872714
                options_text: 'Size: S'
                price: '10.00'
                total: '20.00'
                adjustment_total: '0.00'
                additional_tax_total: '0.00'
                included_tax_total: '0.00'
                discount_total: '0.00'
                pre_tax_amount: '20.00'
                discounted_amount: '20.00'
                compare_at_amount:
                thumbnail_url:
                option_values:
                - id: optval_UkLWZg9DAJ
                  option_type_id: opt_UkLWZg9DAJ
                  name: size-18
                  label: S
                  position: 1
                  color_code:
                  option_type_name: foo-size-28
                  option_type_label: Size
                  image_url:
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                digital_links: []
                external_references: {}
                metadata: {}
                price_source:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                catalog_price: '19.99'
                price_list_id:
                price_list_name:
                catalog_id:
                catalog_name:
                cost_price: '17.00'
                tax_category_id: taxcat_UkLWZg9DAJ
                product_id: prod_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,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/items/{id} -d '{"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
                seller_id:
                preorder: false
                preorder_ships_at:
                quantity: 5
                currency: USD
                name: Product 889758
                slug: product-889758
                options_text: 'Size: S'
                price: '19.99'
                total: '99.95'
                adjustment_total: '0.00'
                additional_tax_total: '0.00'
                included_tax_total: '0.00'
                discount_total: '0.00'
                pre_tax_amount: '99.95'
                discounted_amount: '99.95'
                compare_at_amount:
                thumbnail_url:
                option_values:
                - id: optval_UkLWZg9DAJ
                  option_type_id: opt_UkLWZg9DAJ
                  name: size-19
                  label: S
                  position: 1
                  color_code:
                  option_type_name: foo-size-29
                  option_type_label: Size
                  image_url:
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                digital_links: []
                external_references: {}
                metadata: {}
                price_source:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                catalog_price: '19.99'
                price_list_id:
                price_list_name:
                catalog_id:
                catalog_name:
                cost_price: '17.00'
                tax_category_id: taxcat_UkLWZg9DAJ
                product_id: prod_UkLWZg9DAJ
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/LineItemUpdateParams"
        required: true
    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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /orders/{order_id}/items/{id}
      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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{order_id}/store_credits -d '{"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: mkt_UkLWZg9DAJ
                withdrawal_period_ends_at:
                within_withdrawal_period: false
                shipping_eq_billing_address: false
                cart_id:
                channel_id: ch_UkLWZg9DAJ
                company_id:
                company_name:
                po_document_filename:
                po_document_byte_size:
                number: R1001
                email: ghislaine_labadie@carroll.info
                customer_note:
                po_number:
                currency: USD
                locale: en
                total_quantity: 1
                coupon_code:
                fulfillment_status:
                payment_status:
                completed_at:
                item_total: '10.00'
                discount_total: '0.00'
                tax_total: '0.00'
                included_tax_total: '0.00'
                additional_tax_total: '0.00'
                delivery_total: '100.00'
                fee_total: '0.00'
                gift_card_total: '0.00'
                store_credit_total: '50.00'
                total: '110.00'
                amount_due: '60.00'
                covered_by_store_credit: false
                adjustment_total: '0.00'
                gift_card:
                market:
                  id: mkt_UkLWZg9DAJ
                  name: United States
                  currency: USD
                  default_locale: en
                  tax_inclusive: false
                  default: true
                  country_codes:
                  - US
                  supported_locales:
                  - en
                  created_at: '2026-11-11T12:45:25.448Z'
                  updated_at: '2026-11-11T12:45:25.448Z'
                  tax_provider:
                external_references: {}
                status: draft
                last_ip_address:
                considered_risky: false
                confirmation_delivered: false
                store_owner_notification_delivered:
                metadata: {}
                cancel_note:
                canceled_at:
                approved_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                payment_total: '0.00'
                commission_amount_total: '0.00'
                commission_tax_total: '0.00'
                commission_total: '0.00'
                preferred_stock_location_id:
                po_document_url:
                seller_id:
                order_group_id:
                tags: []
                internal_note:
                internal_note_html:
                approver_id:
                approver_type:
                canceler_id:
                canceler_type:
                created_by_id:
                created_by_type:
                cancel_reason_id:
                cancel_reason_name:
                customer_id: cust_UkLWZg9DAJ
                freight_summary:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/StoreCreditApplyParams"
        required: true
    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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /orders/{order_id}/store_credits
      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,
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /orders -d '{"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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches order number or purchase order number (partial), the
          billing first or last name, or the exact email.
      - name: q[complete]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `complete`.
      - name: q[incomplete]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `incomplete`.
      - name: q[partially_refunded]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `partially_refunded`.
      - name: q[refunded]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `refunded`.
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - 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
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `channel_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `completed_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `considered_risky` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `coupon_code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `currency` | One of the `CurrencyCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `customer_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `delivery_total` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `email` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `fulfillment_status` | One of `backorder`, `canceled`, `partial`, `unfulfilled`, `fulfilled`, `delivered`, `pending`, `ready`, `shipped` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `item_total` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `locale` | One of the `LocaleCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `market_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `order_group_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `payment_status` | One of `none`, `authorized`, `partially_paid`, `paid`, `partially_refunded`, `refunded`, `overcharged`, `voided`, `balance_due`, `credit_owed`, `failed`, `void` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `po_number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `seller_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `status` | One of `draft`, `placed`, `canceled` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `total` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `total_quantity` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[bill_address_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `channel_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `customer_addresses_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customer_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customer_customer_groups_` | `created_at`, `id`, `name`, `updated_at` |
          | `customer_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customer_spree_roles_` | `created_at`, `id`, `name`, `updated_at` |
          | `customer_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `fulfillments_` | `created_at`, `id`, `number`, `updated_at` |
          | `line_items_` | `additional_tax_total`, `adjustment_total`, `cost_price`, `created_at`, `discount_total`, `id`, `included_tax_total`, `non_taxable_adjustment_total`, `order_id`, `pre_tax_amount`, `price`, `quantity`, `tax_category_id`, `taxable_adjustment_total`, `updated_at`, `variant_id` |
          | `line_items_tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |
          | `line_items_variant_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `order_group_` | `created_at`, `currency`, `email`, `id`, `number`, `updated_at` |
          | `order_group_customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `promotions_` | `code`, `created_at`, `expires_at`, `id`, `kind`, `name`, `path`, `promotion_category_id`, `starts_at`, `updated_at` |
          | `promotions_coupon_codes_` | `code`, `created_at`, `id`, `promotion_id`, `state`, `updated_at` |
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `shipments_` | `created_at`, `id`, `number`, `updated_at` |
          | `store_` | `created_at`, `id`, `name`, `updated_at` |
          | `tags_` | `created_at`, `id`, `name`, `updated_at` |

          </Accordion>

          **Sort by:** `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Order
        sortable:
        - channel_id
        - completed_at
        - considered_risky
        - coupon_code
        - created_at
        - currency
        - customer_id
        - delivery_total
        - email
        - fulfillment_status
        - id
        - item_total
        - locale
        - market_id
        - number
        - order_group_id
        - payment_state
        - payment_status
        - po_number
        - seller_id
        - shipment_state
        - status
        - total
        - total_quantity
        - updated_at
      responses:
        '200':
          description: orders found
          content:
            application/json:
              example:
                data:
                - id: or_UkLWZg9DAJ
                  market_id: mkt_UkLWZg9DAJ
                  withdrawal_period_ends_at:
                  within_withdrawal_period: false
                  shipping_eq_billing_address: false
                  cart_id:
                  channel_id: ch_UkLWZg9DAJ
                  company_id:
                  company_name:
                  po_document_filename:
                  po_document_byte_size:
                  number: R1001
                  email: viki_reichel@moorecummerata.us
                  customer_note:
                  po_number:
                  currency: USD
                  locale: en
                  total_quantity: 0
                  coupon_code:
                  fulfillment_status:
                  payment_status:
                  completed_at:
                  item_total: '0.00'
                  discount_total: '0.00'
                  tax_total: '0.00'
                  included_tax_total: '0.00'
                  additional_tax_total: '0.00'
                  delivery_total: '0.00'
                  fee_total:
                  gift_card_total: '0.00'
                  store_credit_total: '0.00'
                  total: '0.00'
                  amount_due: '0.00'
                  covered_by_store_credit: false
                  adjustment_total: '0.00'
                  gift_card:
                  market:
                    id: mkt_UkLWZg9DAJ
                    name: United States
                    currency: USD
                    default_locale: en
                    tax_inclusive: false
                    default: true
                    country_codes:
                    - US
                    supported_locales:
                    - en
                    created_at: '2026-11-11T12:45:25.448Z'
                    updated_at: '2026-11-11T12:45:25.448Z'
                    tax_provider:
                  external_references: {}
                  status: draft
                  last_ip_address:
                  considered_risky: false
                  confirmation_delivered: false
                  store_owner_notification_delivered:
                  metadata: {}
                  cancel_note:
                  canceled_at:
                  approved_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  payment_total: '0.00'
                  commission_amount_total: '0.00'
                  commission_tax_total: '0.00'
                  commission_total: '0.00'
                  preferred_stock_location_id:
                  po_document_url:
                  seller_id:
                  order_group_id:
                  tags: []
                  internal_note:
                  internal_note_html:
                  approver_id:
                  approver_type:
                  canceler_id:
                  canceler_type:
                  created_by_id:
                  created_by_type:
                  cancel_reason_id:
                  cancel_reason_name:
                  customer_id: cust_UkLWZg9DAJ
                  freight_summary:
                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.',
            // Rich text: send HTML. Reads return this as plain text, plus
            // `internal_note_html` with the markup.
            internal_note: '<p>VIP customer — handle with care.</p>',
            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_code: 'US',
              state_code: '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_code: 'US',
              state_code: '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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /orders -d '{"email":"jane@example.com","customer_id":"cus_UkLWZg9DAJ","use_customer_default_address":false,"currency":"USD","market_id":"mkt_UkLWZg9DAJ","channel_id":"ch_UkLWZg9DAJ","locale":"en-US","preferred_stock_location_id":"sloc_UkLWZg9DAJ","customer_note":"Please
          leave at the front desk.","internal_note":"<p>VIP customer — handle with
          care.</p>","metadata":{"external_reference":"subscription_invoice_2026_04","source":"recurring-engine"},"items":[{"variant_id":"variant_k5nR8xLq","quantity":2},{"variant_id":"variant_QXyZ12abCD","quantity":1,"metadata":{"gift":true}}],"shipping_address":{"first_name":"Jane","last_name":"Doe","address1":"350
          Fifth Avenue","address2":"Floor 42","city":"New York","postal_code":"10118","country_code":"US","state_code":"NY","phone":"+1
          212 555 1234","company":"Acme Inc."},"billing_address":{"first_name":"Jane","last_name":"Doe","address1":"350
          Fifth Avenue","city":"New York","postal_code":"10118","country_code":"US","state_code":"NY","phone":"+1
          212 555 1234"},"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: mkt_UkLWZg9DAJ
                withdrawal_period_ends_at:
                within_withdrawal_period: false
                shipping_eq_billing_address: false
                cart_id:
                channel_id: ch_UkLWZg9DAJ
                company_id:
                company_name:
                po_document_filename:
                po_document_byte_size:
                number: R1002
                email: pinned@example.com
                customer_note:
                po_number:
                currency: USD
                locale: en
                total_quantity: 0
                coupon_code:
                fulfillment_status:
                payment_status:
                completed_at:
                item_total: '0.00'
                discount_total: '0.00'
                tax_total: '0.00'
                included_tax_total: '0.00'
                additional_tax_total: '0.00'
                delivery_total: '0.00'
                fee_total: '0.00'
                gift_card_total: '0.00'
                store_credit_total: '0.00'
                total: '0.00'
                amount_due: '0.00'
                covered_by_store_credit: false
                adjustment_total: '0.00'
                gift_card:
                market:
                  id: mkt_UkLWZg9DAJ
                  name: United States
                  currency: USD
                  default_locale: en
                  tax_inclusive: false
                  default: true
                  country_codes:
                  - US
                  supported_locales:
                  - en
                  created_at: '2026-11-11T12:45:25.448Z'
                  updated_at: '2026-11-11T12:45:25.448Z'
                  tax_provider:
                external_references: {}
                status: draft
                last_ip_address:
                considered_risky: false
                confirmation_delivered: false
                store_owner_notification_delivered:
                metadata: {}
                cancel_note:
                canceled_at:
                approved_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                payment_total: '0.00'
                commission_amount_total: '0.00'
                commission_tax_total: '0.00'
                commission_total: '0.00'
                preferred_stock_location_id: sloc_UkLWZg9DAJ
                po_document_url:
                seller_id:
                order_group_id:
                tags: []
                internal_note:
                internal_note_html:
                approver_id:
                approver_type:
                canceler_id:
                canceler_type:
                created_by_id: adm_UkLWZg9DAJ
                created_by_type: admin_user
                cancel_reason_id:
                cancel_reason_name:
                customer_id:
                freight_summary:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/OrderCreateParams"
        required: true
  "/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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{id} -d '{"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: mkt_UkLWZg9DAJ
                withdrawal_period_ends_at:
                within_withdrawal_period: false
                shipping_eq_billing_address: false
                cart_id:
                channel_id: ch_UkLWZg9DAJ
                company_id:
                company_name:
                po_document_filename:
                po_document_byte_size:
                number: R1001
                email: angelic@ogaromaguera.co.uk
                customer_note:
                po_number:
                currency: USD
                locale: en
                total_quantity: 0
                coupon_code:
                fulfillment_status:
                payment_status:
                completed_at:
                item_total: '0.00'
                discount_total: '0.00'
                tax_total: '0.00'
                included_tax_total: '0.00'
                additional_tax_total: '0.00'
                delivery_total: '0.00'
                fee_total:
                gift_card_total: '0.00'
                store_credit_total: '0.00'
                total: '0.00'
                amount_due: '0.00'
                covered_by_store_credit: false
                adjustment_total: '0.00'
                gift_card:
                market:
                  id: mkt_UkLWZg9DAJ
                  name: United States
                  currency: USD
                  default_locale: en
                  tax_inclusive: false
                  default: true
                  country_codes:
                  - US
                  supported_locales:
                  - en
                  created_at: '2026-11-11T12:45:25.448Z'
                  updated_at: '2026-11-11T12:45:25.448Z'
                  tax_provider:
                external_references: {}
                status: draft
                last_ip_address:
                considered_risky: false
                confirmation_delivered: false
                store_owner_notification_delivered:
                metadata: {}
                cancel_note:
                canceled_at:
                approved_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                payment_total: '0.00'
                commission_amount_total: '0.00'
                commission_tax_total: '0.00'
                commission_total: '0.00'
                preferred_stock_location_id:
                po_document_url:
                seller_id:
                order_group_id:
                tags: []
                internal_note:
                internal_note_html:
                approver_id:
                approver_type:
                canceler_id:
                canceler_type:
                created_by_id:
                created_by_type:
                cancel_reason_id:
                cancel_reason_name:
                customer_id: cust_UkLWZg9DAJ
                freight_summary:
        '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: '<p>VIP — gift wrap on next order</p>',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{id} -d '{"email":"updated@example.com","internal_note":"<p>VIP
          — gift wrap on next order</p>"}'
      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: mkt_UkLWZg9DAJ
                withdrawal_period_ends_at:
                within_withdrawal_period: false
                shipping_eq_billing_address: false
                cart_id:
                channel_id: ch_UkLWZg9DAJ
                company_id:
                company_name:
                po_document_filename:
                po_document_byte_size:
                number: R1001
                email: updated@example.com
                customer_note:
                po_number:
                currency: USD
                locale: en
                total_quantity: 0
                coupon_code:
                fulfillment_status:
                payment_status: none
                completed_at:
                item_total: '0.00'
                discount_total: '0.00'
                tax_total: '0.00'
                included_tax_total: '0.00'
                additional_tax_total: '0.00'
                delivery_total: '0.00'
                fee_total: '0.00'
                gift_card_total: '0.00'
                store_credit_total: '0.00'
                total: '0.00'
                amount_due: '0.00'
                covered_by_store_credit: false
                adjustment_total: '0.00'
                gift_card:
                market:
                  id: mkt_UkLWZg9DAJ
                  name: United States
                  currency: USD
                  default_locale: en
                  tax_inclusive: false
                  default: true
                  country_codes:
                  - US
                  supported_locales:
                  - en
                  created_at: '2026-11-11T12:45:25.448Z'
                  updated_at: '2026-11-11T12:45:25.448Z'
                  tax_provider:
                external_references: {}
                status: draft
                last_ip_address:
                considered_risky: false
                confirmation_delivered: false
                store_owner_notification_delivered:
                metadata: {}
                cancel_note:
                canceled_at:
                approved_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                payment_total: '0.00'
                commission_amount_total: '0.00'
                commission_tax_total: '0.00'
                commission_total: '0.00'
                preferred_stock_location_id:
                po_document_url:
                seller_id:
                order_group_id:
                tags: []
                internal_note:
                internal_note_html:
                approver_id:
                approver_type:
                canceler_id:
                canceler_type:
                created_by_id:
                created_by_type:
                cancel_reason_id:
                cancel_reason_name:
                customer_id: cust_UkLWZg9DAJ
                freight_summary:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/OrderUpdateParams"
        required: true
    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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /orders/{id}
      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.

        On a marketplace, an order holding several sellers' goods becomes one
        order per seller, and the response is the order group they belong to
        with those orders nested inside it.


        **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 result = await client.orders.complete('or_UkLWZg9DAJ', {
            notify_customer: true,
          })

          // An order holding several sellers' goods becomes one order per seller.
          const orders = isOrderGroup(result) ? result.orders : [result]
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{id}/complete -d '{"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: mkt_UkLWZg9DAJ
                withdrawal_period_ends_at:
                within_withdrawal_period: true
                shipping_eq_billing_address: false
                cart_id:
                channel_id: ch_UkLWZg9DAJ
                company_id:
                company_name:
                po_document_filename:
                po_document_byte_size:
                number: R1001
                email: lisandra.blanda@grahamryan.biz
                customer_note:
                po_number:
                currency: USD
                locale: en
                total_quantity: 1
                coupon_code:
                fulfillment_status: unfulfilled
                payment_status: paid
                completed_at: '2026-01-15T12:00:00.000Z'
                item_total: '10.00'
                discount_total: '0.00'
                tax_total: '0.00'
                included_tax_total: '0.00'
                additional_tax_total: '0.00'
                delivery_total: '100.00'
                fee_total: '0.00'
                gift_card_total: '0.00'
                store_credit_total: '0.00'
                total: '110.00'
                amount_due: '0.00'
                covered_by_store_credit: false
                adjustment_total: '0.00'
                gift_card:
                market:
                  id: mkt_UkLWZg9DAJ
                  name: United States
                  currency: USD
                  default_locale: en
                  tax_inclusive: false
                  default: true
                  country_codes:
                  - US
                  supported_locales:
                  - en
                  created_at: '2026-11-11T12:45:25.448Z'
                  updated_at: '2026-11-11T12:45:25.448Z'
                  tax_provider:
                external_references: {}
                status: placed
                last_ip_address:
                considered_risky: false
                confirmation_delivered: false
                store_owner_notification_delivered:
                metadata: {}
                cancel_note:
                canceled_at:
                approved_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                payment_total: '110.00'
                commission_amount_total: '0.00'
                commission_tax_total: '0.00'
                commission_total: '0.00'
                preferred_stock_location_id:
                po_document_url:
                seller_id:
                order_group_id:
                tags: []
                internal_note:
                internal_note_html:
                approver_id:
                approver_type:
                canceler_id:
                canceler_type:
                created_by_id:
                created_by_type:
                cancel_reason_id:
                cancel_reason_name:
                customer_id: cust_UkLWZg9DAJ
                freight_summary:
        '422':
          description: order cannot be completed
          content:
            application/json:
              example:
                error:
                  code: order_cannot_complete
                  message: No payment found
                  details:
                    base:
                    - code:
                      message: No payment found
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/OrderCompleteParams"
        required: true
  "/api/v3/admin/orders/{id}/cancel":
    patch:
      summary: Cancel an order
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Cancels a completed order.

        `cancel_reason_id` records why, from the store's own cancellation-reason
        vocabulary (`/admin/order_cancellation_reasons`), and `cancel_note` is a
        staff-facing note; both are shown on the order afterwards.

        Stock is always released — the goods are not going out either way — and
        every payment is settled at the gateway, which releases an
        authorization it never drew on and refunds a charge it cannot release.

        `refund_payments` and `refund_amount` govern the shared payment of a
        split checkout, where one payment covers several orders: they decide
        whether this order's share comes back, and how much of it. A
        `refund_amount` on an ordinary order is refused with a 422.

        Set `notify_customer: true` to send the order cancellation email.


        **Required scope:** `write_orders`, plus `write_refunds` with `refund_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',
          })

          // A split checkout: the payment is shared, so what comes back is this order's
          // own share. refund_amount names part of that share, keeping the rest back.
          const order = await client.orders.cancel('or_UkLWZg9DAJ', {
            cancel_reason_id: 'ocr_UkLWZg9DAJ',
            cancel_note: 'Supplier could not deliver in time',
            refund_payments: true,
            refund_amount: '25.00',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{id}/cancel -d '{"cancel_reason_id":"ocr_UkLWZg9DAJ","cancel_note":"Supplier
          could not deliver in time","refund_payments":true,"refund_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: 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: mkt_UkLWZg9DAJ
                withdrawal_period_ends_at:
                within_withdrawal_period: false
                shipping_eq_billing_address: false
                cart_id:
                channel_id: ch_UkLWZg9DAJ
                company_id:
                company_name:
                po_document_filename:
                po_document_byte_size:
                number: R1001
                email: eleanor@zulaufdavis.com
                customer_note:
                po_number:
                currency: USD
                locale: en
                total_quantity: 1
                coupon_code:
                fulfillment_status: canceled
                payment_status: none
                completed_at: '2026-01-15T12:00:00.000Z'
                item_total: '10.00'
                discount_total: '0.00'
                tax_total: '0.00'
                included_tax_total: '0.00'
                additional_tax_total: '0.00'
                delivery_total: '100.00'
                fee_total: '0.00'
                gift_card_total: '0.00'
                store_credit_total: '0.00'
                total: '110.00'
                amount_due: '0.00'
                covered_by_store_credit: false
                adjustment_total: '0.00'
                gift_card:
                market:
                  id: mkt_UkLWZg9DAJ
                  name: United States
                  currency: USD
                  default_locale: en
                  tax_inclusive: false
                  default: true
                  country_codes:
                  - US
                  supported_locales:
                  - en
                  created_at: '2026-11-11T12:45:25.448Z'
                  updated_at: '2026-11-11T12:45:25.448Z'
                  tax_provider:
                external_references: {}
                status: canceled
                last_ip_address:
                considered_risky: false
                confirmation_delivered: false
                store_owner_notification_delivered:
                metadata: {}
                cancel_note:
                canceled_at: '2026-01-15T12:00:00.000Z'
                approved_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                payment_total: '0.00'
                commission_amount_total: '0.00'
                commission_tax_total: '0.00'
                commission_total: '0.00'
                preferred_stock_location_id:
                po_document_url:
                seller_id:
                order_group_id:
                tags: []
                internal_note:
                internal_note_html:
                approver_id:
                approver_type:
                canceler_id: adm_UkLWZg9DAJ
                canceler_type: admin_user
                created_by_id:
                created_by_type:
                cancel_reason_id:
                cancel_reason_name:
                customer_id: cust_UkLWZg9DAJ
                freight_summary:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/OrderCancelParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{id}/approve -d '{ ... }'
      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: mkt_UkLWZg9DAJ
                withdrawal_period_ends_at:
                within_withdrawal_period: true
                shipping_eq_billing_address: false
                cart_id:
                channel_id: ch_UkLWZg9DAJ
                company_id:
                company_name:
                po_document_filename:
                po_document_byte_size:
                number: R1001
                email: del@bashirian.us
                customer_note:
                po_number:
                currency: USD
                locale: en
                total_quantity: 1
                coupon_code:
                fulfillment_status:
                payment_status:
                completed_at: '2026-01-15T12:00:00.000Z'
                item_total: '10.00'
                discount_total: '0.00'
                tax_total: '0.00'
                included_tax_total: '0.00'
                additional_tax_total: '0.00'
                delivery_total: '100.00'
                fee_total: '0.00'
                gift_card_total: '0.00'
                store_credit_total: '0.00'
                total: '110.00'
                amount_due: '110.00'
                covered_by_store_credit: false
                adjustment_total: '0.00'
                gift_card:
                market:
                  id: mkt_UkLWZg9DAJ
                  name: United States
                  currency: USD
                  default_locale: en
                  tax_inclusive: false
                  default: true
                  country_codes:
                  - US
                  supported_locales:
                  - en
                  created_at: '2026-11-11T12:45:25.448Z'
                  updated_at: '2026-11-11T12:45:25.448Z'
                  tax_provider:
                external_references: {}
                status: placed
                last_ip_address:
                considered_risky: false
                confirmation_delivered: false
                store_owner_notification_delivered:
                metadata: {}
                cancel_note:
                canceled_at:
                approved_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                payment_total: '0.00'
                commission_amount_total: '0.00'
                commission_tax_total: '0.00'
                commission_total: '0.00'
                preferred_stock_location_id:
                po_document_url:
                seller_id:
                order_group_id:
                tags: []
                internal_note:
                internal_note_html:
                approver_id: adm_UkLWZg9DAJ
                approver_type: admin_user
                canceler_id:
                canceler_type:
                created_by_id:
                created_by_type:
                cancel_reason_id:
                cancel_reason_name:
                customer_id: cust_UkLWZg9DAJ
                freight_summary:
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{id}/resend_confirmation -d '{ ... }'
      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: mkt_UkLWZg9DAJ
                withdrawal_period_ends_at:
                within_withdrawal_period: true
                shipping_eq_billing_address: false
                cart_id:
                channel_id: ch_UkLWZg9DAJ
                company_id:
                company_name:
                po_document_filename:
                po_document_byte_size:
                number: R1001
                email: michal.cartwright@hintzdeckow.info
                customer_note:
                po_number:
                currency: USD
                locale: en
                total_quantity: 1
                coupon_code:
                fulfillment_status:
                payment_status:
                completed_at: '2026-01-15T12:00:00.000Z'
                item_total: '10.00'
                discount_total: '0.00'
                tax_total: '0.00'
                included_tax_total: '0.00'
                additional_tax_total: '0.00'
                delivery_total: '100.00'
                fee_total: '0.00'
                gift_card_total: '0.00'
                store_credit_total: '0.00'
                total: '110.00'
                amount_due: '110.00'
                covered_by_store_credit: false
                adjustment_total: '0.00'
                gift_card:
                market:
                  id: mkt_UkLWZg9DAJ
                  name: United States
                  currency: USD
                  default_locale: en
                  tax_inclusive: false
                  default: true
                  country_codes:
                  - US
                  supported_locales:
                  - en
                  created_at: '2026-11-11T12:45:25.448Z'
                  updated_at: '2026-11-11T12:45:25.448Z'
                  tax_provider:
                external_references: {}
                status: placed
                last_ip_address:
                considered_risky: false
                confirmation_delivered: false
                store_owner_notification_delivered:
                metadata: {}
                cancel_note:
                canceled_at:
                approved_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                payment_total: '0.00'
                commission_amount_total: '0.00'
                commission_tax_total: '0.00'
                commission_total: '0.00'
                preferred_stock_location_id:
                po_document_url:
                seller_id:
                order_group_id:
                tags: []
                internal_note:
                internal_note_html:
                approver_id:
                approver_type:
                canceler_id:
                canceler_type:
                created_by_id:
                created_by_type:
                cancel_reason_id:
                cancel_reason_name:
                customer_id: cust_UkLWZg9DAJ
                freight_summary:
  "/api/v3/admin/orders/{id}/resend_digital_links":
    post:
      summary: Resend digital download links
      tags:
      - Orders
      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.resendDigitalLinks('or_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{id}/resend_digital_links -d '{ ... }'
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Emails the customer their download links for the digital products on
        this order again. Nothing is sent when the order has no digital links or
        the store does not send transactional emails. Use it when the original
        email was lost; to restore used-up downloads or an expired link, reset
        the digital link instead.


        **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
      - name: id
        in: path
        required: true
        description: Order ID
        schema:
          type: string
      responses:
        '200':
          description: digital links resent
          content:
            application/json:
              example:
                id: or_UkLWZg9DAJ
                market_id: mkt_UkLWZg9DAJ
                withdrawal_period_ends_at:
                within_withdrawal_period: true
                shipping_eq_billing_address: false
                cart_id:
                channel_id: ch_UkLWZg9DAJ
                company_id:
                company_name:
                po_document_filename:
                po_document_byte_size:
                number: R1001
                email: ivana@schmidtfeest.com
                customer_note:
                po_number:
                currency: USD
                locale: en
                total_quantity: 1
                coupon_code:
                fulfillment_status:
                payment_status:
                completed_at: '2026-01-15T12:00:00.000Z'
                item_total: '10.00'
                discount_total: '0.00'
                tax_total: '0.00'
                included_tax_total: '0.00'
                additional_tax_total: '0.00'
                delivery_total: '100.00'
                fee_total: '0.00'
                gift_card_total: '0.00'
                store_credit_total: '0.00'
                total: '110.00'
                amount_due: '110.00'
                covered_by_store_credit: false
                adjustment_total: '0.00'
                gift_card:
                market:
                  id: mkt_UkLWZg9DAJ
                  name: United States
                  currency: USD
                  default_locale: en
                  tax_inclusive: false
                  default: true
                  country_codes:
                  - US
                  supported_locales:
                  - en
                  created_at: '2026-11-11T12:45:25.448Z'
                  updated_at: '2026-11-11T12:45:25.448Z'
                  tax_provider:
                external_references: {}
                status: placed
                last_ip_address:
                considered_risky: false
                confirmation_delivered: false
                store_owner_notification_delivered:
                metadata: {}
                cancel_note:
                canceled_at:
                approved_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                payment_total: '0.00'
                commission_amount_total: '0.00'
                commission_tax_total: '0.00'
                commission_total: '0.00'
                preferred_stock_location_id:
                po_document_url:
                seller_id:
                order_group_id:
                tags: []
                internal_note:
                internal_note_html:
                approver_id:
                approver_type:
                canceler_id:
                canceler_type:
                created_by_id:
                created_by_type:
                cancel_reason_id:
                cancel_reason_name:
                customer_id: cust_UkLWZg9DAJ
                freight_summary:
              schema:
                "$ref": "#/components/schemas/Order"
  "/api/v3/admin/returns":
    get:
      summary: List returns
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Every return in the store, across all orders.

        **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: returns } = await client.returns.list({
            status_eq: 'requested',
            sort: '-created_at',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /returns -d '{"status_eq":"requested","sort":"-created_at"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of number (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `status` | One of `requested`, `approved`, `received`, `refunded`, `canceled` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[order_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `order_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `order_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_channel_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `order_customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `order_fulfillments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_line_items_` | `additional_tax_total`, `adjustment_total`, `cost_price`, `created_at`, `discount_total`, `id`, `included_tax_total`, `non_taxable_adjustment_total`, `order_id`, `pre_tax_amount`, `price`, `quantity`, `tax_category_id`, `taxable_adjustment_total`, `updated_at`, `variant_id` |
          | `order_order_group_` | `created_at`, `currency`, `email`, `id`, `number`, `updated_at` |
          | `order_promotions_` | `code`, `created_at`, `expires_at`, `id`, `kind`, `name`, `path`, `promotion_category_id`, `starts_at`, `updated_at` |
          | `order_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `order_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_shipments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_store_` | `created_at`, `id`, `name`, `updated_at` |
          | `order_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `reason_` | `active`, `created_at`, `id`, `name`, `updated_at` |

          </Accordion>

          **Sort by:** `created_at`, `id`, `number`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Return
        sortable:
        - created_at
        - id
        - number
        - status
        - updated_at
      responses:
        '200':
          description: returns listed
          content:
            application/json:
              example:
                data:
                - id: ret_UkLWZg9DAJ
                  number: RET1001
                  status: requested
                  order_id: or_UkLWZg9DAJ
                  reason_id:
                  refund_total: '10.00'
                  refund_tax_total: '0.00'
                  approved_at:
                  received_at:
                  refunded_at:
                  canceled_at:
                  external_references: {}
                  memo: Item did not fit
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  stock_location_id: sloc_UkLWZg9DAJ
                  created_by_id:
                  created_by_type:
                  refunded_total: '0.00'
                  refundable_total: '10.00'
                  documents: []
                  labels: []
                  deliveries: []
                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/Return"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/orders/{order_id}/returns":
    get:
      summary: List order returns
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The returns opened on one 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: returns } = await client.orders.returns.list('or_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/returns
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of number (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `status` | One of `requested`, `approved`, `received`, `refunded`, `canceled` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[order_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `order_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `order_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_channel_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `order_customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `order_fulfillments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_line_items_` | `additional_tax_total`, `adjustment_total`, `cost_price`, `created_at`, `discount_total`, `id`, `included_tax_total`, `non_taxable_adjustment_total`, `order_id`, `pre_tax_amount`, `price`, `quantity`, `tax_category_id`, `taxable_adjustment_total`, `updated_at`, `variant_id` |
          | `order_order_group_` | `created_at`, `currency`, `email`, `id`, `number`, `updated_at` |
          | `order_promotions_` | `code`, `created_at`, `expires_at`, `id`, `kind`, `name`, `path`, `promotion_category_id`, `starts_at`, `updated_at` |
          | `order_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `order_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_shipments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_store_` | `created_at`, `id`, `name`, `updated_at` |
          | `order_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `reason_` | `active`, `created_at`, `id`, `name`, `updated_at` |

          </Accordion>

          **Sort by:** `created_at`, `id`, `number`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Return
        sortable:
        - created_at
        - id
        - number
        - status
        - updated_at
      responses:
        '200':
          description: returns listed
          content:
            application/json:
              example:
                data:
                - id: ret_UkLWZg9DAJ
                  number: RET1001
                  status: requested
                  order_id: or_UkLWZg9DAJ
                  reason_id:
                  refund_total: '10.00'
                  refund_tax_total: '0.00'
                  approved_at:
                  received_at:
                  refunded_at:
                  canceled_at:
                  external_references: {}
                  memo: Item did not fit
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  stock_location_id: sloc_UkLWZg9DAJ
                  created_by_id:
                  created_by_type:
                  refunded_total: '0.00'
                  refundable_total: '10.00'
                  documents: []
                  labels: []
                  deliveries: []
                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/Return"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Create a return
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Opens a return on a completed order for fulfilled units the customer is sending back.

        **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 orderReturn = await client.orders.returns.create('or_UkLWZg9DAJ', {
            reason_id: 'rar_UkLWZg9DAJ',
            items: [{ fulfillment_item_id: 'fi_UkLWZg9DAJ', quantity: 1 }],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{order_id}/returns -d '{"reason_id":"rar_UkLWZg9DAJ","items":[{"fulfillment_item_id":"fi_UkLWZg9DAJ","quantity":1}]}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      responses:
        '201':
          description: return opened
          content:
            application/json:
              example:
                id: ret_gbHJdmfrXB
                number: RET1002
                status: requested
                order_id: or_gbHJdmfrXB
                reason_id:
                refund_total: '10.00'
                refund_tax_total: '0.00'
                approved_at:
                received_at:
                refunded_at:
                canceled_at:
                external_references: {}
                memo: Too small
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                stock_location_id: sloc_UkLWZg9DAJ
                created_by_id: adm_UkLWZg9DAJ
                created_by_type: admin_user
                refunded_total: '0.00'
                refundable_total: '10.00'
                documents: []
                labels: []
                deliveries: []
              schema:
                "$ref": "#/components/schemas/Return"
        '422':
          description: more returned than was fulfilled
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: Only 1 of Product 2002493 can be returned
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReturnCreateParams"
        required: true
  "/api/v3/admin/orders/{order_id}/returns/{id}":
    patch:
      summary: Update a return
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Edits the warehouse, reason, memo or metadata of a return. Its status moves only through the approve, receive, refund and cancel actions.

        **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 orderReturn = await client.orders.returns.update('or_UkLWZg9DAJ', 'ret_UkLWZg9DAJ', {
            stock_location_id: 'sloc_UkLWZg9DAJ',
            memo: 'Send to the returns warehouse',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/returns/{id} -d '{"stock_location_id":"sloc_UkLWZg9DAJ","memo":"Send
          to the returns warehouse"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Return prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: return updated
          content:
            application/json:
              example:
                id: ret_UkLWZg9DAJ
                number: RET1001
                status: requested
                order_id: or_UkLWZg9DAJ
                reason_id: rar_UkLWZg9DAJ
                refund_total: '10.00'
                refund_tax_total: '0.00'
                approved_at:
                received_at:
                refunded_at:
                canceled_at:
                external_references: {}
                memo: Customer shipped it back with a tracking number
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                stock_location_id: sloc_UkLWZg9DAJ
                created_by_id:
                created_by_type:
                refunded_total: '0.00'
                refundable_total: '10.00'
                documents: []
                labels: []
                deliveries: []
              schema:
                "$ref": "#/components/schemas/Return"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReturnUpdateParams"
        required: true
  "/api/v3/admin/orders/{order_id}/returns/{id}/approve":
    patch:
      summary: Approve a return
      tags:
      - Orders
      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 orderReturn = await client.orders.returns.approve('or_UkLWZg9DAJ', 'ret_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/returns/{id}/approve -d '{ ...
          }'
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Accepts a requested return so the customer can send the goods back. Only a requested return can be approved; receive it once the goods arrive.

        **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
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Return prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: return approved
          content:
            application/json:
              example:
                id: ret_UkLWZg9DAJ
                number: RET1001
                status: approved
                order_id: or_UkLWZg9DAJ
                reason_id:
                refund_total: '10.00'
                refund_tax_total: '0.00'
                approved_at: '2026-01-15T12:00:00Z'
                received_at:
                refunded_at:
                canceled_at:
                external_references: {}
                memo: Item did not fit
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                stock_location_id: sloc_UkLWZg9DAJ
                created_by_id: adm_UkLWZg9DAJ
                created_by_type: admin_user
                refunded_total: '0.00'
                refundable_total: '10.00'
                documents: []
                labels: []
                deliveries: []
              schema:
                "$ref": "#/components/schemas/Return"
        '422':
          description: the return is not requested
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: Not requested
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/orders/{order_id}/returns/{id}/receive":
    patch:
      summary: Receive a return
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Records what arrived on an approved return. Omit `items` to receive everything as requested and resellable; send rows for a partial or damaged receipt.

        **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',
          })

          // Omit `items` to receive everything as requested and resellable.
          const orderReturn = await client.orders.returns.receive('or_UkLWZg9DAJ', 'ret_UkLWZg9DAJ', {
            items: [{ return_line_item_id: 'rli_UkLWZg9DAJ', quantity: 1, resellable: false }],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/returns/{id}/receive -d '{"items":[{"return_line_item_id":"rli_UkLWZg9DAJ","quantity":1,"resellable":false}]}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Return prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: return received
          content:
            application/json:
              example:
                id: ret_UkLWZg9DAJ
                number: RET1001
                status: received
                order_id: or_UkLWZg9DAJ
                reason_id:
                refund_total: '10.00'
                refund_tax_total: '0.00'
                approved_at: '2026-01-15T12:00:00Z'
                received_at: '2026-01-15T12:00:00Z'
                refunded_at:
                canceled_at:
                external_references: {}
                memo: Item did not fit
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                stock_location_id: sloc_UkLWZg9DAJ
                created_by_id:
                created_by_type:
                refunded_total: '0.00'
                refundable_total: '10.00'
                documents: []
                labels: []
                deliveries: []
              schema:
                "$ref": "#/components/schemas/Return"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReturnReceiveParams"
  "/api/v3/admin/orders/{order_id}/returns/{id}/refund":
    patch:
      summary: Refund a return
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Pays the customer back for a received return, to store credit or through the original payment.

        **Required scope:** `write_orders` and `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 orderReturn = await client.orders.returns.refund('or_UkLWZg9DAJ', 'ret_UkLWZg9DAJ', {
            amount: '29.99',
            refund_method: 'original_payment',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/returns/{id}/refund -d '{"amount":"29.99","refund_method":"original_payment"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Return prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: return refunded
          content:
            application/json:
              example:
                id: ret_UkLWZg9DAJ
                number: RET1001
                status: refunded
                order_id: or_UkLWZg9DAJ
                reason_id:
                refund_total: '10.00'
                refund_tax_total: '0.00'
                approved_at: '2026-01-14T12:00:00Z'
                received_at: '2026-01-15T12:00:00Z'
                refunded_at: '2026-01-15T12:00:00Z'
                canceled_at:
                external_references: {}
                memo: Item did not fit
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                stock_location_id: sloc_UkLWZg9DAJ
                created_by_id:
                created_by_type:
                refunded_total: '10.00'
                refundable_total: '0.00'
                documents: []
                labels: []
                deliveries: []
              schema:
                "$ref": "#/components/schemas/Return"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReturnRefundParams"
  "/api/v3/admin/orders/{order_id}/returns/{id}/cancel":
    patch:
      summary: Cancel a return
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Withdraws a return whose goods have not been received.

        **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 orderReturn = await client.orders.returns.cancel('or_UkLWZg9DAJ', 'ret_UkLWZg9DAJ', {
            reason: 'Customer decided to keep the item',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/returns/{id}/cancel -d '{"reason":"Customer
          decided to keep the item"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Return prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: return canceled
          content:
            application/json:
              example:
                id: ret_UkLWZg9DAJ
                number: RET1001
                status: canceled
                order_id: or_UkLWZg9DAJ
                reason_id:
                refund_total: '10.00'
                refund_tax_total: '0.00'
                approved_at:
                received_at:
                refunded_at:
                canceled_at: '2026-01-15T12:00:00Z'
                external_references: {}
                memo: |-
                  Item did not fit
                  Customer changed their mind
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                stock_location_id: sloc_UkLWZg9DAJ
                created_by_id:
                created_by_type:
                refunded_total: '0.00'
                refundable_total: '10.00'
                documents: []
                labels: []
                deliveries: []
              schema:
                "$ref": "#/components/schemas/Return"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReturnCancelParams"
  "/api/v3/admin/orders/{order_id}/returns/{return_id}/labels":
    get:
      summary: List return labels
      tags:
      - Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The shipping labels issued for sending one return back to the 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: labels } = await client.orders.returns.labels.list('or_UkLWZg9DAJ', 'ret_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/returns/{return_id}/labels
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: return_id
        in: path
        required: true
        description: Return prefixed 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: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[carrier_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `carrier` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `source` | One of `purchased`, `uploaded` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `status` | One of `purchased`, `refund_requested`, `refunded` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `tracking_number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `carrier`, `created_at`, `id`, `source`, `status`, `tracking_number`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: ShippingLabel
        sortable:
        - carrier
        - created_at
        - id
        - source
        - status
        - tracking_number
        - updated_at
      responses:
        '200':
          description: labels listed
          content:
            application/json:
              example:
                data:
                - id: lbl_UkLWZg9DAJ
                  source: purchased
                  status: purchased
                  carrier: ups
                  carrier_name: UPS
                  service: Ground
                  tracking_number: 1Z879E930346830006
                  currency: USD
                  format: pdf
                  external_id: shp_3
                  metadata: {}
                  refunded_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  owner_id: ret_UkLWZg9DAJ
                  owner_type: return
                  cost: '7.25'
                  integration_id:
                  file_pending: false
                  download_url:
                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/ShippingLabel"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/orders/{order_id}/returns/{return_id}/labels/{id}/refund":
    patch:
      summary: Refund a return label
      tags:
      - Orders
      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 label = await client.orders.returns.labels.refund(
            'or_UkLWZg9DAJ',
            'ret_UkLWZg9DAJ',
            'lbl_UkLWZg9DAJ',
          )
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/returns/{return_id}/labels/{id}/refund
          -d '{ ... }'
      operationId: return_labels_refund
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Asks the carrier to refund a purchased return label the customer never used, such as when the return is canceled. An uploaded label has nothing to refund.

        **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
        schema:
          type: string
      - name: order_id
        in: path
        required: true
        description: Order prefixed ID
        schema:
          type: string
      - name: return_id
        in: path
        required: true
        description: Return prefixed ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Shipping label prefixed ID
        schema:
          type: string
      responses:
        '200':
          description: refund filed
          content:
            application/json:
              example:
                id: lbl_UkLWZg9DAJ
                source: purchased
                status: refunded
                carrier: ups
                carrier_name: UPS
                service: Ground
                tracking_number: 1Z879E930346830007
                currency: USD
                format: pdf
                external_id: shp_4
                metadata: {}
                refunded_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                owner_id: ret_UkLWZg9DAJ
                owner_type: return
                cost: '7.25'
                integration_id:
                file_pending: false
                download_url:
              schema:
                "$ref": "#/components/schemas/ShippingLabel"
        '422':
          description: uploaded labels cannot be refunded
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: An uploaded label was not bought through Spree and cannot
                    be refunded — delete it instead
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/payment_methods/{payment_method_id}/custom_fields":
    get:
      summary: List payment method custom fields
      tags:
      - Payment Methods
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the payment method's custom field values.

        **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: customFields } = await client.customFields('payment_method', 'pm_UkLWZg9DAJ').list()
      - lang: bash
        label: Spree CLI
        source: spree api get /payment_methods/{payment_method_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: payment_method_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/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()
      - lang: bash
        label: Spree CLI
        source: spree api get /payment_methods
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - 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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `active` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `storefront_visible` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `type` | Type | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `active`, `created_at`, `id`, `name`, `position`, `storefront_visible`, `type`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: PaymentMethod
        sortable:
        - active
        - created_at
        - id
        - name
        - position
        - storefront_visible
        - type
        - updated_at
      responses:
        '200':
          description: payment methods found
          content:
            application/json:
              example:
                data:
                - id: pm_UkLWZg9DAJ
                  name: Check 3
                  description:
                  type: check
                  session_required: false
                  source_required: false
                  metadata: {}
                  active: true
                  capture_method:
                  resolved_capture_method: checkout
                  storefront_visible: true
                  position: 1
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  preferences: {}
                  logo_url:
                  docs_url:
                  third_party: false
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Create a payment method
      tags:
      - Payment Methods
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds a payment method to the store. `type` is a shorthand from the
        payment method types endpoint, and `preferences` takes the values its
        preference schema declares (gateway credentials among them).


        **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 paymentMethod = await client.paymentMethods.create({
            type: 'check',
            name: 'Bank transfer',
            description: 'Pay by bank transfer within 14 days.',
            active: true,
            storefront_visible: true,
            capture_method: 'manual',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /payment_methods -d '{"type":"check","name":"Bank transfer","description":"Pay
          by bank transfer within 14 days.","active":true,"storefront_visible":true,"capture_method":"manual"}'
      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: payment method created
          content:
            application/json:
              example:
                id: pm_gbHJdmfrXB
                name: Bank transfer
                description: Pay by bank transfer within 14 days.
                type: check
                session_required: false
                source_required: false
                metadata: {}
                active: true
                capture_method: manual
                resolved_capture_method: manual
                storefront_visible: true
                position: 2
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                preferences: {}
                logo_url:
                docs_url:
                third_party: false
        '422':
          description: unknown payment method type
          content:
            application/json:
              example:
                error:
                  code: unknown_payment_method_type
                  message: Unknown type
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PaymentMethodCreateParams"
        required: true
  "/api/v3/admin/payment_methods/types":
    get:
      summary: List available payment provider types
      tags:
      - Payment Methods
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns every registered payment provider with the JSON Schema of its `preferences`. `installed` marks a provider the store already has, which a "Provider" picker leaves out.

        **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()
      - lang: bash
        label: Spree CLI
        source: spree api get /payment_methods/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:
                  schema:
                    type: object
                    properties:
                      dummy_key:
                        type: string
                        default: PUBLICKEY123
                      dummy_secret_key:
                        type:
                        - string
                        - 'null'
                        x-spree-secret: true
                    additionalProperties: false
                  logo_url:
                  docs_url:
                  third_party: true
                  installed: false
                - type: check
                  label: Check
                  description:
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                  logo_url:
                  docs_url:
                  third_party: false
                  installed: true
                - type: custom_payment_source_method
                  label: Custom Payment Source Method
                  description:
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                  logo_url:
                  docs_url:
                  third_party: false
                  installed: false
                - type: store_credit
                  label: Store Credit
                  description:
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                  logo_url:
                  docs_url:
                  third_party: false
                  installed: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /payment_methods/{id}
      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 7
                description:
                type: check
                session_required: false
                source_required: false
                metadata: {}
                active: true
                capture_method:
                resolved_capture_method: checkout
                storefront_visible: true
                position: 1
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                preferences: {}
                logo_url:
                docs_url:
                third_party: false
    patch:
      summary: Update a payment method
      tags:
      - Payment Methods
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Updates a payment method. Its `type` is fixed once created.

        **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 paymentMethod = await client.paymentMethods.update('pm_UkLWZg9DAJ', {
            name: 'Cheque',
            storefront_visible: false,
            position: 2,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /payment_methods/{id} -d '{"name":"Cheque","storefront_visible":false,"position":2}'
      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: payment method updated
          content:
            application/json:
              example:
                id: pm_UkLWZg9DAJ
                name: Cheque
                description:
                type: check
                session_required: false
                source_required: false
                metadata: {}
                active: true
                capture_method:
                resolved_capture_method: checkout
                storefront_visible: false
                position: 2
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                preferences: {}
                logo_url:
                docs_url:
                third_party: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PaymentMethodUpdateParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/payments
      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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[avs_response_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `amount` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `avs_response` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `cvv_response_code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `cvv_response_message` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `response_code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `state` | One of `checkout`, `processing`, `pending`, `completed`, `failed`, `void`, `invalid` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `status` | One of `checkout`, `processing`, `pending`, `completed`, `failed`, `void`, `invalid` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[order_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `order_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `order_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_channel_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `order_customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `order_fulfillments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_line_items_` | `additional_tax_total`, `adjustment_total`, `cost_price`, `created_at`, `discount_total`, `id`, `included_tax_total`, `non_taxable_adjustment_total`, `order_id`, `pre_tax_amount`, `price`, `quantity`, `tax_category_id`, `taxable_adjustment_total`, `updated_at`, `variant_id` |
          | `order_order_group_` | `created_at`, `currency`, `email`, `id`, `number`, `updated_at` |
          | `order_promotions_` | `code`, `created_at`, `expires_at`, `id`, `kind`, `name`, `path`, `promotion_category_id`, `starts_at`, `updated_at` |
          | `order_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `order_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_shipments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_store_` | `created_at`, `id`, `name`, `updated_at` |
          | `order_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `payment_method_` | `active`, `created_at`, `id`, `name`, `position`, `storefront_visible`, `type`, `updated_at` |

          </Accordion>

          **Sort by:** `amount`, `avs_response`, `created_at`, `cvv_response_code`, `cvv_response_message`, `id`, `response_code`, `state`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Payment
        sortable:
        - amount
        - avs_response
        - created_at
        - cvv_response_code
        - cvv_response_message
        - id
        - response_code
        - state
        - status
        - updated_at
      responses:
        '200':
          description: payments found
          content:
            application/json:
              example:
                data:
                - id: py_UkLWZg9DAJ
                  payment_method_id: pm_UkLWZg9DAJ
                  response_code: BGS-343039b69b86
                  number: R1001-P1
                  status: completed
                  amount: '110.00'
                  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-01-15T12:00:00.000Z'
                    updated_at: '2026-01-15T12:00:00.000Z'
                  metadata: {}
                  avs_response:
                  cvv_response_code:
                  cvv_response_message:
                  gateway_dashboard_payment_url: https://dashboard.bogus.example/payments/BGS-343039b69b86
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  avs_risky: false
                  cvv_risky: false
                  can_void: true
                  can_capture: false
                  captured_amount: '0.00'
                  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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{order_id}/payments -d '{"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: R1002-P1
                status: checkout
                amount: '110.00'
                source_type:
                source_id:
                source:
                metadata: {}
                avs_response:
                cvv_response_code:
                cvv_response_message:
                gateway_dashboard_payment_url:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                avs_risky: false
                cvv_risky: false
                can_void: true
                can_capture: true
                captured_amount: '0.00'
                order_id: or_gbHJdmfrXB
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PaymentCreateParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/payments/{id}
      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-4a236d40ef07
                number: R1001-P1
                status: completed
                amount: '110.00'
                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-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                metadata: {}
                avs_response:
                cvv_response_code:
                cvv_response_message:
                gateway_dashboard_payment_url: https://dashboard.bogus.example/payments/BGS-4a236d40ef07
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                avs_risky: false
                cvv_risky: false
                can_void: true
                can_capture: false
                captured_amount: '0.00'
                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, in full or for part of the authorized amount.

        **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')
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/payments/{id}/capture -d '{ ...
          }'
      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-ccc19f06b194
                number: R1001-P1
                status: completed
                amount: '110.00'
                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-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                metadata: {}
                avs_response:
                cvv_response_code:
                cvv_response_message:
                gateway_dashboard_payment_url: https://dashboard.bogus.example/payments/BGS-ccc19f06b194
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                avs_risky: false
                cvv_risky: false
                can_void: true
                can_capture: false
                captured_amount: '110.00'
                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"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PaymentCaptureParams"
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/payments/{id}/void -d '{ ... }'
      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-11f2e975ba0c
                number: R1001-P1
                status: void
                amount: '110.00'
                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-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                metadata: {}
                avs_response:
                cvv_response_code:
                cvv_response_message:
                gateway_dashboard_payment_url: https://dashboard.bogus.example/payments/void-BGS-11f2e975ba0c
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                avs_risky: false
                cvv_risky: false
                can_void: false
                can_capture: false
                captured_amount: '0.00'
                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).
      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: priceLists } = await client.priceLists.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /price_lists
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - name: page
        in: query
        required: false
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        schema:
          type: integer
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - 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
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `catalog_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `ends_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `match_policy` | One of `all`, `any` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `starts_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `status` | One of `draft`, `active`, `inactive`, `scheduled` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `catalog_id`, `created_at`, `ends_at`, `id`, `match_policy`, `name`, `position`, `starts_at`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: PriceList
        sortable:
        - catalog_id
        - created_at
        - ends_at
        - id
        - match_policy
        - name
        - position
        - starts_at
        - status
        - updated_at
      responses:
        '200':
          description: price lists found
          content:
            application/json:
              example:
                data:
                - id: pl_UkLWZg9DAJ
                  name: Wholesale
                  description:
                  status: draft
                  position: 1
                  match_policy: all
                  adjust_compare_at: false
                  starts_at:
                  ends_at:
                  deleted_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  price_adjustment_percentage:
                  automatic_pricing: false
                  currently_active: false
                  products_count: 0
                  prices_count: 0
                  price_adjustment_tiers: []
                - id: pl_gbHJdmfrXB
                  name: Holiday
                  description:
                  status: draft
                  position: 2
                  match_policy: all
                  adjust_compare_at: false
                  starts_at:
                  ends_at:
                  deleted_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  price_adjustment_percentage:
                  automatic_pricing: false
                  currently_active: false
                  products_count: 0
                  prices_count: 0
                  price_adjustment_tiers: []
                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).
      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',
          })

          // Server-to-server one-shot create. Ship the rules that gate the list
          // and the exact per-variant prices in a single request — variants in
          // `prices` implicitly become part of the list (upserted on the unique
          // key `(variant_id, currency, price_list_id)`). Curating whole products
          // goes through `client.priceLists.products` instead.
          const priceList = await client.priceLists.create({
            name: 'EU wholesale',
            description: 'Tiered pricing for verified B2B customers',
            match_policy: 'all',
            starts_at: '2026-06-01T00:00:00Z',
            ends_at: '2026-09-01T00:00:00Z',
            rules: [
              {
                type: 'customer_group_rule',
                preferences: { customer_group_ids: ['cg_aBc123'] },
              },
              {
                type: 'volume_rule',
                preferences: { min_quantity: 10 },
              },
            ],
            prices: [
              {
                variant_id: 'variant_xY9',
                currency: 'USD',
                amount: '19.99',
                compare_at_amount: '24.99',
              },
              {
                variant_id: 'variant_aB7',
                currency: 'USD',
                amount: '21.99',
              },
            ],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /price_lists -d '{"name":"EU wholesale","description":"Tiered
          pricing for verified B2B customers","match_policy":"all","starts_at":"2026-06-01T00:00:00Z","ends_at":"2026-09-01T00:00:00Z","rules":[{"type":"customer_group_rule","preferences":{"customer_group_ids":["cg_aBc123"]}},{"type":"volume_rule","preferences":{"min_quantity":10}}],"prices":[{"variant_id":"variant_xY9","currency":"USD","amount":"19.99","compare_at_amount":"24.99"},{"variant_id":"variant_aB7","currency":"USD","amount":"21.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 list created (server-to-server — rules + prices)
          content:
            application/json:
              example:
                id: pl_EfhxLZ9ck8
                name: EU wholesale
                description:
                status: draft
                position: 3
                match_policy: all
                adjust_compare_at: false
                starts_at:
                ends_at:
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                price_adjustment_percentage:
                automatic_pricing: false
                currently_active: false
                products_count: 1
                prices_count: 2
                price_adjustment_tiers: []
              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:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PriceListCreateParams"
        required: true
  "/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)."
      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 priceList = await client.priceLists.get('pl_xxx')
      - lang: bash
        label: Spree CLI
        source: spree api get /price_lists/{id}
      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
                adjust_compare_at: false
                starts_at:
                ends_at:
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                price_adjustment_percentage:
                automatic_pricing: false
                currently_active: false
                products_count: 0
                prices_count: 0
                price_adjustment_tiers: []
              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).
      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 priceList = await client.priceLists.update('pl_xxx', {
            name: 'Wholesale (Q3)',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /price_lists/{id} -d '{"name":"Wholesale (Q3)"}'
      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
                adjust_compare_at: false
                starts_at:
                ends_at:
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                price_adjustment_percentage:
                automatic_pricing: false
                currently_active: false
                products_count: 0
                prices_count: 0
                price_adjustment_tiers: []
              schema:
                "$ref": "#/components/schemas/PriceList"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PriceListUpdateParams"
        required: true
    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).
      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.priceLists.delete('pl_xxx')
      - lang: bash
        label: Spree CLI
        source: spree api delete /price_lists/{id}
      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).
      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 priceList = await client.priceLists.activate('pl_xxx')
      - lang: bash
        label: Spree CLI
        source: spree api patch /price_lists/{id}/activate -d '{ ... }'
      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
                adjust_compare_at: false
                starts_at:
                ends_at:
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                price_adjustment_percentage:
                automatic_pricing: false
                currently_active: true
                products_count: 0
                prices_count: 0
                price_adjustment_tiers: []
              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)."
      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 priceList = await client.priceLists.deactivate('pl_xxx')
      - lang: bash
        label: Spree CLI
        source: spree api patch /price_lists/{id}/deactivate -d '{ ... }'
      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 3
                description:
                status: inactive
                position: 1
                match_policy: all
                adjust_compare_at: false
                starts_at:
                ends_at:
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                price_adjustment_percentage:
                automatic_pricing: false
                currently_active: false
                products_count: 0
                prices_count: 0
                price_adjustment_tiers: []
              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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /prices -d '{"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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches the variant's SKU, option value or product name, as variant
          search does.
      - name: page
        in: query
        required: false
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        schema:
          type: integer
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - 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
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[amount_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `amount` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `compare_at_amount` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `currency` | One of the `CurrencyCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `min_quantity` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `price_list_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `variant_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[price_list_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `price_list_` | `catalog_id`, `created_at`, `ends_at`, `id`, `match_policy`, `name`, `position`, `starts_at`, `status`, `updated_at` |
          | `variant_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `variant_option_values_` | `created_at`, `id`, `label`, `name`, `position`, `updated_at` |
          | `variant_product_` | `available_on`, `created_at`, `description`, `discontinue_on`, `id`, `name`, `price`, `seller_id`, `slug`, `status`, `updated_at` |
          | `variant_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `variant_tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |

          </Accordion>

          **Sort by:** `amount`, `compare_at_amount`, `created_at`, `currency`, `id`, `min_quantity`, `price_list_id`, `updated_at`, `variant_id`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Price
        sortable:
        - amount
        - compare_at_amount
        - created_at
        - currency
        - id
        - min_quantity
        - price_list_id
        - updated_at
        - variant_id
      responses:
        '200':
          description: prices found
          content:
            application/json:
              example:
                data:
                - id: price_UkLWZg9DAJ
                  currency: USD
                  amount: '19.99'
                  compare_at_amount:
                  price_list_id:
                  min_quantity: 1
                  variant_id: variant_UkLWZg9DAJ
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                - id: price_gbHJdmfrXB
                  currency: USD
                  amount: '19.99'
                  compare_at_amount:
                  price_list_id:
                  min_quantity: 1
                  variant_id: variant_gbHJdmfrXB
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                - id: price_EfhxLZ9ck8
                  currency: USD
                  amount: '5.00'
                  compare_at_amount:
                  price_list_id: pl_UkLWZg9DAJ
                  min_quantity: 1
                  variant_id: variant_gbHJdmfrXB
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                meta:
                  page: 1
                  limit: 25
                  count: 3
                  pages: 1
                  from: 1
                  to: 3
                  in: 3
                  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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /prices -d '{"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
                currency: EUR
                amount: '9.99'
                compare_at_amount:
                price_list_id:
                min_quantity: 1
                variant_id: variant_EfhxLZ9ck8
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/Price"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PriceCreateParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /prices/{id}
      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
                currency: USD
                amount: '5.00'
                compare_at_amount:
                price_list_id: pl_UkLWZg9DAJ
                min_quantity: 1
                variant_id: variant_gbHJdmfrXB
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /prices/{id} -d '{"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
                currency: USD
                amount: '12.34'
                compare_at_amount:
                price_list_id: pl_UkLWZg9DAJ
                min_quantity: 1
                variant_id: variant_gbHJdmfrXB
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/Price"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PriceUpdateParams"
        required: 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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /prices/{id}
      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',
              },
            ],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /prices/bulk_upsert -d '{"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:
              "$ref": "#/components/schemas/PriceBulkUpsertParams"
        required: true
  "/api/v3/admin/prices/bulk_destroy":
    delete:
      summary: Bulk-delete prices
      tags:
      - Pricing
      x-spree-agent: false
      x-spree-agent-reason: Deletes many prices in one call behind a single confirmation;
        delete_resource removes them one at a time.
      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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api delete /prices/bulk_destroy -d '{"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:
              "$ref": "#/components/schemas/PriceBulkDestroyParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /products/{product_id}/custom_fields
      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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /products/{product_id}/custom_fields -d '{"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
                field_type: long_text
                key: custom.description
                value: A longer description
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                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: Custom field definition has already been taken
                  details:
                    custom_field_definition_id:
                    - value: 1
                      code: taken
                      message: has already been taken
                      specific: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CustomFieldCreateParams"
        required: true
  "/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)."
      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.get('prod_UkLWZg9DAJ', 'cf_AbC123XyZ')
      - lang: bash
        label: Spree CLI
        source: spree api get /products/{product_id}/custom_fields/{id}
      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
                field_type: short_text
                key: custom.title
                value: wool
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                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).
      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.update('prod_UkLWZg9DAJ', 'cf_AbC123XyZ', {
            value: 'cotton',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /products/{product_id}/custom_fields/{id} -d '{"value":"cotton"}'
      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
                field_type: short_text
                key: custom.title
                value: cotton
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                storefront_visible: true
                custom_field_definition_id: cfdef_UkLWZg9DAJ
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CustomFieldUpdateParams"
        required: true
    delete:
      summary: Delete a product custom field
      tags:
      - Products
      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',
          })

          await client.products.customFields.delete('prod_UkLWZg9DAJ', 'cf_AbC123XyZ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /products/{product_id}/custom_fields/{id}
      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/{product_id}/digital_assets":
    parameters:
    - name: product_id
      in: path
      required: true
      description: Product ID
      schema:
        type: string
    get:
      summary: List product digital assets
      tags:
      - Products
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the downloadable files attached to the product's variants, oldest first.

        **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: digitalAssets } = await client.products.digitalAssets.list('prod_86Rf07xd4z')
      - lang: bash
        label: Spree CLI
        source: spree api get /products/{product_id}/digital_assets
      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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: DigitalAsset
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: digital assets found
          content:
            application/json:
              example:
                data:
                - id: dig_UkLWZg9DAJ
                  variant_id: variant_UkLWZg9DAJ
                  filename: thinking-cat.jpg
                  content_type: image/jpeg
                  authorized_clicks:
                  authorized_days:
                  byte_size: 18090
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  provider_type:
                  provider_name: File
                  download_url: http://www.example.com/rails/active_storage/disk/eyJfcmFpbHMiOnsiZGF0YSI6eyJrZXkiOiJ0Z252N2l0MG55YnkwbHhkczg5Y2hteTd6aXlvIiwiZGlzcG9zaXRpb24iOiJhdHRhY2htZW50OyBmaWxlbmFtZT1cInRoaW5raW5nLWNhdC5qcGdcIjsgZmlsZW5hbWUqPVVURi04Jyd0aGlua2luZy1jYXQuanBnIiwiY29udGVudF90eXBlIjoiaW1hZ2UvanBlZyIsInNlcnZpY2VfbmFtZSI6InRlc3QifSwiZXhwIjoiMjAyNi0wMS0xNVQxMjowNTowMC4wMDBaIiwicHVyIjoiYmxvYl9rZXkifX0=--709f2019d409ca81185d256a48389bc187a4544d/thinking-cat.jpg
                  effective_authorized_clicks: 5
                  effective_authorized_days: 7
                  provider_settings: {}
                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/DigitalAsset"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Create a product digital asset
      tags:
      - Products
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Attaches a downloadable file to one of the product's variants (the
        default variant when `variant_id` is omitted). Upload the file first
        through `POST /api/v3/admin/files` with `visibility: 'private'`, then
        send its `signed_id` here. A provider-backed asset sends
        `provider_type` and `provider_settings` instead of a file.


        **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',
          })

          // `signed_id` comes from `files.upload()` with `visibility: 'private'`.
          const digitalAsset = await client.products.digitalAssets.create('prod_86Rf07xd4z', {
            signed_id: 'eyJfcmFpbHMiOnsiZGF0YSI6MTIzfX0=--abc123',
            authorized_clicks: 5,
            authorized_days: 30,
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /products/{product_id}/digital_assets -d '{"signed_id":"eyJfcmFpbHMiOnsiZGF0YSI6MTIzfX0=--abc123","authorized_clicks":5,"authorized_days":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: digital asset created
          content:
            application/json:
              example:
                id: dig_gbHJdmfrXB
                variant_id: variant_UkLWZg9DAJ
                filename: manual.pdf
                content_type: image/jpeg
                authorized_clicks: 5
                authorized_days: 30
                byte_size: 18090
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                provider_type:
                provider_name: File
                download_url: http://www.example.com/rails/active_storage/disk/eyJfcmFpbHMiOnsiZGF0YSI6eyJrZXkiOiJhOXR0cGNpbmxxbThvbmtlNHM1NmI2Y3gxMWVzIiwiZGlzcG9zaXRpb24iOiJhdHRhY2htZW50OyBmaWxlbmFtZT1cIm1hbnVhbC5wZGZcIjsgZmlsZW5hbWUqPVVURi04JydtYW51YWwucGRmIiwiY29udGVudF90eXBlIjoiaW1hZ2UvanBlZyIsInNlcnZpY2VfbmFtZSI6InRlc3QifSwiZXhwIjoiMjAyNi0wMS0xNVQxMjowNTowMC4wMDBaIiwicHVyIjoiYmxvYl9rZXkifX0=--4aedc095f285621c27efe025cd8841f58d6d09d3/manual.pdf
                effective_authorized_clicks: 5
                effective_authorized_days: 30
                provider_settings: {}
              schema:
                "$ref": "#/components/schemas/DigitalAsset"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DigitalAssetCreateParams"
        required: true
  "/api/v3/admin/products/{product_id}/digital_assets/{id}":
    parameters:
    - name: product_id
      in: path
      required: true
      description: Product ID
      schema:
        type: string
    - name: id
      in: path
      required: true
      description: Digital asset ID
      schema:
        type: string
    patch:
      summary: Update a product digital asset
      tags:
      - Products
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Changes an asset's download limits, or replaces its file with a new
        private `signed_id`. Links customers already received keep working and
        serve the new file.


        **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',
          })

          // `null` falls back to the store's download settings.
          const digitalAsset = await client.products.digitalAssets.update(
            'prod_86Rf07xd4z',
            'dig_k5nR8xLqPz',
            { authorized_clicks: 10, authorized_days: null },
          )
      - lang: bash
        label: Spree CLI
        source: spree api patch /products/{product_id}/digital_assets/{id} -d '{"authorized_clicks":10,"authorized_days":null}'
      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: digital asset updated
          content:
            application/json:
              example:
                id: dig_UkLWZg9DAJ
                variant_id: variant_UkLWZg9DAJ
                filename: thinking-cat.jpg
                content_type: image/jpeg
                authorized_clicks: 10
                authorized_days:
                byte_size: 18090
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                provider_type:
                provider_name: File
                download_url: http://www.example.com/rails/active_storage/disk/eyJfcmFpbHMiOnsiZGF0YSI6eyJrZXkiOiIwZXp6d3IzMzE3ajRoem9kc3Awc2czN3EzMnhzIiwiZGlzcG9zaXRpb24iOiJhdHRhY2htZW50OyBmaWxlbmFtZT1cInRoaW5raW5nLWNhdC5qcGdcIjsgZmlsZW5hbWUqPVVURi04Jyd0aGlua2luZy1jYXQuanBnIiwiY29udGVudF90eXBlIjoiaW1hZ2UvanBlZyIsInNlcnZpY2VfbmFtZSI6InRlc3QifSwiZXhwIjoiMjAyNi0wMS0xNVQxMjowNTowMC4wMDBaIiwicHVyIjoiYmxvYl9rZXkifX0=--506612a6a2fda890a0b082043117cbc516d49d89/thinking-cat.jpg
                effective_authorized_clicks: 10
                effective_authorized_days: 7
                provider_settings: {}
              schema:
                "$ref": "#/components/schemas/DigitalAsset"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DigitalAssetUpdateParams"
        required: true
  "/api/v3/admin/products/{product_id}/translations":
    get:
      summary: List product translations
      tags:
      - Products
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the full translation matrix for the product: the source value and content type per translatable field, plus the translated value for every supported locale.

        **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',
          })

          // Source values and every locale's translations, including the product's variants and options.
          const translations = await client.products.translations.get('prod_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /products/{product_id}/translations
      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:
        '200':
          description: translations found
          content:
            application/json:
              example:
                data:
                  resource_id: prod_UkLWZg9DAJ
                  resource_type: product
                  translations:
                    de:
                      name: Espressomaschine
                      description:
                      slug: espressomaschine
                      meta_description:
                      meta_title:
                      translated_field_count: 2
                    fr:
                      name:
                      description:
                      slug:
                      meta_description:
                      meta_title:
                      translated_field_count: 0
                  fields:
                  - key: name
                    type: string
                    source: Espresso Machine
                  - key: description
                    type: html
                    source: |-
                      Atque esse occaecati recusandae quam sit blanditiis accusamus. Et temporibus optio quos est esse nobis odit nihil. Magnam quo illum voluptas dolorum quidem. Modi rerum labore praesentium laborum veritatis iusto.
                      Tempora exercitationem sed vero itaque nihil odio distinctio explicabo. Corporis nesciunt minus veritatis beatae quaerat facilis similique eius. Esse dolores suscipit iusto totam velit ipsa.
                      Aut saepe quibusdam mollitia amet. Eius beatae facilis asperiores maiores. Fuga doloremque provident perspiciatis natus a quaerat reprehenderit occaecati. Eius deserunt commodi placeat delectus.
                      Consequatur quas ipsum voluptas quis. Vel cumque molestiae magnam optio. Recusandae eum cum sequi autem fugiat animi tenetur.
                  - key: slug
                    type: string
                    source: espresso-machine
                  - key: meta_description
                    type: string
                    source:
                  - key: meta_title
                    type: string
                    source:
                  default_locale: en
                  supported_locales:
                  - de
                  - en
                  - fr
  "/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({
            search: 'shirt',
            status_eq: 'active',
            sort: '-created_at',
            limit: 25,
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /products -d '{"search":"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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches product name or variant SKU (partial, case-insensitive),
          and the store's searchable custom fields.
      - name: q[ascend_by_price]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `ascend_by_price`.
      - name: q[descend_by_price]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `descend_by_price`.
      - name: q[in_categories][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        description: Applies `in_categories` to the given value.
      - name: q[in_category]
        in: query
        required: false
        schema:
          type: string
        description: Applies `in_category` to the given value.
      - name: q[in_collection]
        in: query
        required: false
        schema:
          type: string
        description: Applies `in_collection` to the given value.
      - name: q[in_stock]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `in_stock`.
      - name: q[in_taxon]
        in: query
        required: false
        schema:
          type: string
        description: Applies `in_taxon` to the given value.
      - name: q[not_discontinued]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `not_discontinued`.
      - name: q[out_of_stock]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `out_of_stock`.
      - name: q[price_between][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: number
          minItems: 2
          maxItems: 2
        description: Applies `price_between` to the given value.
      - name: q[price_gte]
        in: query
        required: false
        schema:
          type: number
        description: Applies `price_gte` to the given value.
      - name: q[price_lte]
        in: query
        required: false
        schema:
          type: number
        description: Applies `price_lte` to the given value.
      - name: q[search_by_name]
        in: query
        required: false
        schema:
          type: string
        description: Applies `search_by_name` to the given value.
      - name: q[with_option_value_ids][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        description: Applies `with_option_value_ids` to the given value.
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `available_on` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `description` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `discontinue_on` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `price` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `seller_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `slug` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `status` | One of `draft`, `active`, `archived`, `proposed`, `rejected` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[categories_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `categories_` | `automatic`, `children_count`, `created_at`, `depth`, `id`, `name`, `parent_id`, `permalink`, `position`, `pretty_name`, `products_count`, `updated_at` |
          | `categories_parent_` | `automatic`, `children_count`, `created_at`, `depth`, `id`, `name`, `parent_id`, `permalink`, `position`, `pretty_name`, `products_count`, `updated_at` |
          | `channels_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `collections_` | `automatic`, `created_at`, `id`, `name`, `permalink`, `position`, `products_count`, `sort_order`, `updated_at` |
          | `default_variant_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `default_variant_option_values_` | `created_at`, `id`, `label`, `name`, `position`, `updated_at` |
          | `default_variant_prices_` | `amount`, `compare_at_amount`, `created_at`, `currency`, `id`, `min_quantity`, `price_list_id`, `updated_at`, `variant_id` |
          | `default_variant_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `default_variant_tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |
          | `labels_` | `created_at`, `id`, `name`, `updated_at` |
          | `option_types_` | `created_at`, `id`, `kind`, `label`, `name`, `position`, `updated_at` |
          | `product_categories_` | `category_id`, `created_at`, `id`, `position`, `product_id`, `updated_at` |
          | `product_type_` | `created_at`, `id`, `name`, `updated_at` |
          | `product_type_option_types_` | `created_at`, `id`, `kind`, `label`, `name`, `position`, `updated_at` |
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `store_` | `created_at`, `id`, `name`, `updated_at` |
          | `tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `variants_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `variants_option_values_` | `created_at`, `id`, `label`, `name`, `position`, `updated_at` |
          | `variants_prices_` | `amount`, `compare_at_amount`, `created_at`, `currency`, `id`, `min_quantity`, `price_list_id`, `updated_at`, `variant_id` |
          | `variants_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `variants_tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |

          </Accordion>

          Also filters and sorts on the store's searchable custom fields, as `q[cf_<namespace>_<key>_<predicate>]` and `sort=cf_<namespace>_<key>`.

          **Sort by:** `available_on`, `best_selling`, `created_at`, `description`, `discontinue_on`, `id`, `manual`, `name`, `price`, `seller_id`, `slug`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Product
        sortable:
        - available_on
        - best_selling
        - created_at
        - description
        - discontinue_on
        - id
        - manual
        - name
        - price
        - seller_id
        - slug
        - status
        - updated_at
        custom_fields: true
      responses:
        '200':
          description: products found
          content:
            application/json:
              example:
                data:
                - id: prod_UkLWZg9DAJ
                  name: Product 1376550
                  slug: product-1376550
                  meta_title:
                  meta_description:
                  meta_keywords:
                  variant_count: 1
                  available_on:
                  preorder_ships_at:
                  purchasable: true
                  preorder: false
                  in_stock: false
                  backorderable: true
                  available: true
                  description: Saepe quas nemo facilis nam. Voluptatem facere nam
                    impedit sunt minus possimus totam ullam. Pariatur ullam sed tenetur
                    quibusdam deleniti.
                  description_html: Saepe quas nemo facilis nam. Voluptatem facere
                    nam impedit sunt minus possimus totam ullam. Pariatur ullam sed
                    tenetur quibusdam deleniti.
                  default_variant_id: variant_UkLWZg9DAJ
                  buy_box_variant_id: variant_UkLWZg9DAJ
                  thumbnail_url:
                  tags: []
                  price:
                    id: price_UkLWZg9DAJ
                    currency: USD
                    amount: '19.99'
                    compare_at_amount:
                    price_list_id:
                    min_quantity: 1
                    variant_id: variant_UkLWZg9DAJ
                    created_at: '2026-01-15T12:00:00.000Z'
                    updated_at: '2026-01-15T12:00:00.000Z'
                  original_price:
                  seller_id:
                  external_references: {}
                  status: active
                  metadata: {}
                  deleted_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  delivery_profile_id: fp_UkLWZg9DAJ
                  seller_name:
                  product_type_id:
                  tax_category_id: taxcat_UkLWZg9DAJ
                  total_on_hand: 0
                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',
            // Rich text: send HTML. Reads return this as plain text, plus
            // `description_html` with the markup.
            description: '<p>Soft, organic cotton.</p>',
            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_levels: [{ 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_levels: [{ stock_location_id: 'sloc_UkLWZg9DAJ', count_on_hand: 30 }],
              },
            ],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /products -d '{"name":"Premium T-Shirt","description":"<p>Soft,
          organic cotton.</p>","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_levels":[{"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_levels":[{"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: 1
                available_on:
                preorder_ships_at:
                purchasable: false
                preorder: false
                in_stock: false
                backorderable: false
                available: false
                description:
                description_html:
                default_variant_id: variant_gbHJdmfrXB
                buy_box_variant_id: variant_gbHJdmfrXB
                thumbnail_url:
                tags: []
                price:
                original_price:
                seller_id:
                external_references: {}
                status: draft
                metadata: {}
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivery_profile_id: fp_UkLWZg9DAJ
                seller_name:
                product_type_id:
                tax_category_id:
                total_on_hand: 0
              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:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductCreateParams"
        required: true
  "/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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /products/{id} -d '{"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 1412061
                slug: product-1412061
                meta_title:
                meta_description:
                meta_keywords:
                variant_count: 1
                available_on:
                preorder_ships_at:
                purchasable: true
                preorder: false
                in_stock: false
                backorderable: true
                available: true
                description: Illo error explicabo cupiditate consequatur. Et expedita
                  velit laborum iure. Harum sit eaque nam ipsam maiores.
                description_html: Illo error explicabo cupiditate consequatur. Et
                  expedita velit laborum iure. Harum sit eaque nam ipsam maiores.
                default_variant_id: variant_UkLWZg9DAJ
                buy_box_variant_id: variant_UkLWZg9DAJ
                thumbnail_url:
                tags: []
                price:
                  id: price_UkLWZg9DAJ
                  currency: USD
                  amount: '19.99'
                  compare_at_amount:
                  price_list_id:
                  min_quantity: 1
                  variant_id: variant_UkLWZg9DAJ
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                original_price:
                seller_id:
                external_references: {}
                status: active
                metadata: {}
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivery_profile_id: fp_UkLWZg9DAJ
                seller_name:
                product_type_id:
                tax_category_id: taxcat_UkLWZg9DAJ
                total_on_hand: 0
              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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /products/{id} -d '{"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-1435339
                meta_title:
                meta_description:
                meta_keywords:
                variant_count: 1
                available_on:
                preorder_ships_at:
                purchasable: true
                preorder: false
                in_stock: false
                backorderable: true
                available: true
                description: Laborum nostrum nemo fugit temporibus consectetur omnis.
                  Necessitatibus voluptas ut delectus aperiam incidunt tenetur. Alias
                  at perspiciatis laborum similique. Fugit adipisci iure porro architecto
                  odit. Alias enim quis rem reprehenderit temporibus. Hic quae rem
                  aspernatur tempore in. Praesentium assumenda sequi quis quasi. Laboriosam
                  est tempore doloribus cumque inventore vero laborum minus. Reiciendis
                  autem quia eligendi possimus beatae enim. Impedit nemo quae odit
                  dolor velit possimus commodi. Sequi ullam dolorum odio at quam vitae.
                  Corporis ipsa alias tempora accusantium. Adipisci sapiente illum
                  id voluptatum aut illo tempora.
                description_html: |-
                  Laborum nostrum nemo fugit temporibus consectetur omnis. Necessitatibus voluptas ut delectus aperiam incidunt tenetur. Alias at perspiciatis laborum similique. Fugit adipisci iure porro architecto odit.
                  Alias enim quis rem reprehenderit temporibus. Hic quae rem aspernatur tempore in. Praesentium assumenda sequi quis quasi. Laboriosam est tempore doloribus cumque inventore vero laborum minus. Reiciendis autem quia eligendi possimus beatae enim.
                  Impedit nemo quae odit dolor velit possimus commodi. Sequi ullam dolorum odio at quam vitae. Corporis ipsa alias tempora accusantium. Adipisci sapiente illum id voluptatum aut illo tempora.
                default_variant_id: variant_UkLWZg9DAJ
                buy_box_variant_id: variant_UkLWZg9DAJ
                thumbnail_url:
                tags: []
                price:
                  id: price_UkLWZg9DAJ
                  currency: USD
                  amount: '19.99'
                  compare_at_amount:
                  price_list_id:
                  min_quantity: 1
                  variant_id: variant_UkLWZg9DAJ
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                original_price:
                seller_id:
                external_references: {}
                status: active
                metadata: {}
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivery_profile_id: fp_UkLWZg9DAJ
                seller_name:
                product_type_id:
                tax_category_id: taxcat_UkLWZg9DAJ
                total_on_hand: 0
              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:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductUpdateParams"
        required: true
    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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /products/{id}
      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
        '422':
          description: deletion refused by a store rule
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: This product is under an active supplier contract.
                  details:
                    base:
                    - code: under_contract
                      message: This product is under an active supplier contract.
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/products/{id}/clone":
    parameters:
    - name: id
      in: path
      required: true
      description: Product ID
      schema:
        type: string
    post:
      summary: Clone a product
      tags:
      - Products
      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 copy = await client.products.clone('prod_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api post /products/{id}/clone -d '{ ... }'
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Creates a draft copy of a product, named "COPY OF …", with its variants,
        prices, stock locations, images, categories, channels and tags; stock on
        hand starts at zero. Use it to start a similar product from an existing
        one instead of building it from scratch.


        **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: product cloned
          content:
            application/json:
              example:
                id: prod_gbHJdmfrXB
                name: COPY OF Product 1472357
                slug: copy-of-product-1472357
                meta_title:
                meta_description:
                meta_keywords:
                variant_count: 1
                available_on:
                preorder_ships_at:
                purchasable: true
                preorder: false
                in_stock: false
                backorderable: true
                available: false
                description: Dolore facere hic laboriosam sapiente nobis. Doloribus
                  deleniti quasi esse aliquid voluptatem. Rem voluptate omnis suscipit
                  adipisci laudantium. Deleniti error dolorum ratione dolor assumenda
                  iusto. Laborum non rem sapiente temporibus quam inventore. Voluptatum
                  magnam hic molestias laudantium necessitatibus. Totam ducimus provident
                  aliquam repellendus nam maxime error natus. Ex aspernatur nostrum
                  deserunt maxime quis occaecati expedita dolore. Debitis est laboriosam
                  modi aspernatur cumque. Sapiente ab corrupti quos doloremque eius.
                  Laborum officiis culpa voluptate fuga sed. Nemo possimus vel architecto
                  quo modi. Velit aut non iusto exercitationem nostrum nemo. Velit
                  illo nisi quaerat perspiciatis facilis temporibus quae esse.
                description_html: |-
                  Dolore facere hic laboriosam sapiente nobis. Doloribus deleniti quasi esse aliquid voluptatem. Rem voluptate omnis suscipit adipisci laudantium.
                  Deleniti error dolorum ratione dolor assumenda iusto. Laborum non rem sapiente temporibus quam inventore. Voluptatum magnam hic molestias laudantium necessitatibus. Totam ducimus provident aliquam repellendus nam maxime error natus.
                  Ex aspernatur nostrum deserunt maxime quis occaecati expedita dolore. Debitis est laboriosam modi aspernatur cumque. Sapiente ab corrupti quos doloremque eius.
                  Laborum officiis culpa voluptate fuga sed. Nemo possimus vel architecto quo modi. Velit aut non iusto exercitationem nostrum nemo. Velit illo nisi quaerat perspiciatis facilis temporibus quae esse.
                default_variant_id: variant_gbHJdmfrXB
                buy_box_variant_id: variant_gbHJdmfrXB
                thumbnail_url:
                tags: []
                price:
                  id: price_gbHJdmfrXB
                  currency: USD
                  amount: '19.99'
                  compare_at_amount:
                  price_list_id:
                  min_quantity: 1
                  variant_id: variant_gbHJdmfrXB
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                original_price:
                seller_id:
                external_references: {}
                status: draft
                metadata: {}
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivery_profile_id: fp_UkLWZg9DAJ
                seller_name:
                product_type_id:
                tax_category_id: taxcat_UkLWZg9DAJ
                total_on_hand: 0
              schema:
                "$ref": "#/components/schemas/Product"
  "/api/v3/admin/products/bulk_status_update":
    post:
      summary: Bulk-update product status
      tags:
      - Products
      x-spree-agent: false
      x-spree-agent-reason: Writes the status column for many products at once, skipping
        the status workflows and their events; products_activate, products_archive
        and products_draft run them.
      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).
      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.products.bulkStatusUpdate({
            ids: ['prod_UkLWZg9DAJ', 'prod_9XbR2kQwLm'],
            status: 'archived',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /products/bulk_status_update -d '{"ids":["prod_UkLWZg9DAJ","prod_9XbR2kQwLm"],"status":"archived"}'
      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:
              "$ref": "#/components/schemas/ProductBulkStatusParams"
        required: true
  "/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 (category) in `category_ids`.
        Categories from sibling stores are silently ignored.


        **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 result = await client.products.bulkAddToCategories({
            ids: ['prod_UkLWZg9DAJ', 'prod_9XbR2kQwLm'],
            category_ids: ['cat_AbC123XyZ'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /products/bulk_add_to_categories -d '{"ids":["prod_UkLWZg9DAJ","prod_9XbR2kQwLm"],"category_ids":["cat_AbC123XyZ"]}'
      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:
              "$ref": "#/components/schemas/ProductBulkCategoriesParams"
        required: true
  "/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).
      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.products.bulkRemoveFromCategories({
            ids: ['prod_UkLWZg9DAJ', 'prod_9XbR2kQwLm'],
            category_ids: ['cat_AbC123XyZ'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /products/bulk_remove_from_categories -d '{"ids":["prod_UkLWZg9DAJ","prod_9XbR2kQwLm"],"category_ids":["cat_AbC123XyZ"]}'
      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:
              "$ref": "#/components/schemas/ProductBulkCategoriesParams"
        required: true
  "/api/v3/admin/products/bulk_add_to_collections":
    post:
      summary: Bulk-add products to collections
      tags:
      - Products
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Attaches each product in `ids` to every manual collection in `collection_ids`.
        Automatic (rule-based) and sibling-store collections are silently ignored.


        **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 result = await client.products.bulkAddToCollections({
            ids: ['prod_UkLWZg9DAJ', 'prod_9XbR2kQwLm'],
            collection_ids: ['coll_AbC123XyZq'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /products/bulk_add_to_collections -d '{"ids":["prod_UkLWZg9DAJ","prod_9XbR2kQwLm"],"collection_ids":["coll_AbC123XyZq"]}'
      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 collections
          content:
            application/json:
              example:
                product_count: 1
                collection_count: 1
              schema:
                type: object
                properties:
                  product_count:
                    type: integer
                  collection_count:
                    type: integer
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductBulkCollectionsParams"
        required: true
  "/api/v3/admin/products/bulk_remove_from_collections":
    post:
      summary: Bulk-remove products from collections
      tags:
      - Products
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Detaches each product in `ids` from every collection in `collection_ids`.

        **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 result = await client.products.bulkRemoveFromCollections({
            ids: ['prod_UkLWZg9DAJ', 'prod_9XbR2kQwLm'],
            collection_ids: ['coll_AbC123XyZq'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /products/bulk_remove_from_collections -d '{"ids":["prod_UkLWZg9DAJ","prod_9XbR2kQwLm"],"collection_ids":["coll_AbC123XyZq"]}'
      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 collections
          content:
            application/json:
              example:
                product_count: 1
                collection_count: 1
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductBulkCollectionsParams"
        required: true
  "/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).
      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.products.bulkAddToChannels({
            ids: ['prod_UkLWZg9DAJ', 'prod_9XbR2kQwLm'],
            channel_ids: ['channel_AbC123XyZ'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /products/bulk_add_to_channels -d '{"ids":["prod_UkLWZg9DAJ","prod_9XbR2kQwLm"],"channel_ids":["channel_AbC123XyZ"]}'
      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:
              "$ref": "#/components/schemas/ProductBulkChannelsParams"
        required: true
  "/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).
      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.products.bulkRemoveFromChannels({
            ids: ['prod_UkLWZg9DAJ', 'prod_9XbR2kQwLm'],
            channel_ids: ['channel_AbC123XyZ'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /products/bulk_remove_from_channels -d '{"ids":["prod_UkLWZg9DAJ","prod_9XbR2kQwLm"],"channel_ids":["channel_AbC123XyZ"]}'
      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:
              "$ref": "#/components/schemas/ProductBulkChannelsParams"
        required: true
  "/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).
      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.products.bulkAddTags({
            ids: ['prod_UkLWZg9DAJ', 'prod_9XbR2kQwLm'],
            tags: ['summer', 'sale'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /products/bulk_add_tags -d '{"ids":["prod_UkLWZg9DAJ","prod_9XbR2kQwLm"],"tags":["summer","sale"]}'
      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:
              "$ref": "#/components/schemas/BulkTagsParams"
        required: true
  "/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).
      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.products.bulkRemoveTags({
            ids: ['prod_UkLWZg9DAJ', 'prod_9XbR2kQwLm'],
            tags: ['summer'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /products/bulk_remove_tags -d '{"ids":["prod_UkLWZg9DAJ","prod_9XbR2kQwLm"],"tags":["summer"]}'
      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:
              "$ref": "#/components/schemas/BulkTagsParams"
        required: true
  "/api/v3/admin/products/bulk_destroy":
    delete:
      summary: Bulk-delete products
      tags:
      - Products
      x-spree-agent: false
      x-spree-agent-reason: Deletes many products in one call behind a single confirmation;
        delete_resource removes them one at a time.
      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).
      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.products.bulkDestroy({
            ids: ['prod_UkLWZg9DAJ', 'prod_9XbR2kQwLm'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api delete /products/bulk_destroy -d '{"ids":["prod_UkLWZg9DAJ","prod_9XbR2kQwLm"]}'
      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:
              "$ref": "#/components/schemas/ProductBulkDestroyParams"
        required: true
  "/api/v3/admin/products/{id}/approve":
    parameters:
    - name: id
      in: path
      required: true
      description: Product ID
      schema:
        type: string
    patch:
      summary: Approve a submitted product
      tags:
      - Products
      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.approve('prod_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api patch /products/{id}/approve -d '{ ... }'
      security:
      - api_key: []
        bearer_auth: []
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      description: |-
        Puts a product a seller submitted for review on sale, and closes the
        submission. Only a product awaiting review can be approved.

        **Required scope:** `write_products` (for API-key authentication).
      responses:
        '200':
          description: product approved
          content:
            application/json:
              example:
                id: prod_gbHJdmfrXB
                name: Product 1628682
                slug: product-1628682
                meta_title:
                meta_description:
                meta_keywords:
                variant_count: 1
                available_on:
                preorder_ships_at:
                purchasable: true
                preorder: false
                in_stock: false
                backorderable: true
                available: true
                description: Eligendi minus placeat hic culpa. Explicabo ea et earum
                  dolor facilis pariatur dolores recusandae. Placeat ut qui optio
                  a veritatis. Ipsam ex delectus reiciendis dolorum cupiditate. Consectetur
                  perferendis blanditiis sunt itaque. Velit odio aliquid hic accusamus
                  ipsa autem quasi. Repellat deserunt officia nobis aliquid sint iusto
                  officiis. Repudiandae natus vitae dolore quam accusamus magnam.
                  Itaque maxime voluptatem cupiditate ratione odit porro sed. Asperiores
                  aliquid dicta consequuntur eum quo. Deleniti recusandae laborum
                  cumque mollitia nisi exercitationem dignissimos.
                description_html: |-
                  Eligendi minus placeat hic culpa. Explicabo ea et earum dolor facilis pariatur dolores recusandae. Placeat ut qui optio a veritatis.
                  Ipsam ex delectus reiciendis dolorum cupiditate. Consectetur perferendis blanditiis sunt itaque. Velit odio aliquid hic accusamus ipsa autem quasi.
                  Repellat deserunt officia nobis aliquid sint iusto officiis. Repudiandae natus vitae dolore quam accusamus magnam. Itaque maxime voluptatem cupiditate ratione odit porro sed. Asperiores aliquid dicta consequuntur eum quo. Deleniti recusandae laborum cumque mollitia nisi exercitationem dignissimos.
                default_variant_id: variant_gbHJdmfrXB
                buy_box_variant_id: variant_gbHJdmfrXB
                thumbnail_url:
                tags: []
                price:
                  id: price_gbHJdmfrXB
                  currency: USD
                  amount: '19.99'
                  compare_at_amount:
                  price_list_id:
                  min_quantity: 1
                  variant_id: variant_gbHJdmfrXB
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                original_price:
                seller_id:
                external_references: {}
                status: active
                metadata: {}
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivery_profile_id: fp_UkLWZg9DAJ
                seller_name:
                product_type_id:
                tax_category_id: taxcat_UkLWZg9DAJ
                total_on_hand: 0
              schema:
                "$ref": "#/components/schemas/Product"
        '422':
          description: the product is not awaiting review
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: This product is not awaiting review.
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/products/{id}/reject":
    parameters:
    - name: id
      in: path
      required: true
      description: Product ID
      schema:
        type: string
    patch:
      summary: Reject a submitted product
      tags:
      - Products
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Turns down a product a seller submitted for review. The `reason` is
        sent back to the seller, who can fix the product and submit it again.


        **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',
          })

          // The seller sees the reason, fixes the product and submits it again.
          const product = await client.products.reject('prod_86Rf07xd4z', {
            reason: 'Photos are too dark',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /products/{id}/reject -d '{"reason":"Photos are too
          dark"}'
      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: product rejected
          content:
            application/json:
              example:
                id: prod_gbHJdmfrXB
                name: Product 1654387
                slug: product-1654387
                meta_title:
                meta_description:
                meta_keywords:
                variant_count: 1
                available_on:
                preorder_ships_at:
                purchasable: true
                preorder: false
                in_stock: false
                backorderable: true
                available: false
                description: Iste blanditiis quos vero ipsam reprehenderit quae. Culpa
                  recusandae ut quisquam facilis enim dolorum eius. Sapiente explicabo
                  animi necessitatibus perspiciatis doloribus aspernatur nobis. Labore
                  similique ipsa debitis voluptate a. Nemo occaecati magnam quos voluptatibus
                  amet. Facilis quis aperiam corporis corrupti enim. Voluptate dignissimos
                  alias exercitationem repudiandae eligendi rerum hic. Facilis sed
                  doloremque dicta porro saepe. Ipsam alias et ipsum voluptatum aperiam
                  molestiae aliquam tempora. Quod ipsa quas eos hic corrupti dignissimos
                  dolorum occaecati. Commodi quis animi at possimus laborum beatae.
                  Aliquam vero suscipit reiciendis dolor placeat. Deleniti corporis
                  tempora accusamus quae nesciunt animi. Numquam occaecati sapiente
                  accusantium amet illum. Vero odio reprehenderit ipsa esse aliquid
                  autem ad.
                description_html: |-
                  Iste blanditiis quos vero ipsam reprehenderit quae. Culpa recusandae ut quisquam facilis enim dolorum eius. Sapiente explicabo animi necessitatibus perspiciatis doloribus aspernatur nobis. Labore similique ipsa debitis voluptate a.
                  Nemo occaecati magnam quos voluptatibus amet. Facilis quis aperiam corporis corrupti enim. Voluptate dignissimos alias exercitationem repudiandae eligendi rerum hic.
                  Facilis sed doloremque dicta porro saepe. Ipsam alias et ipsum voluptatum aperiam molestiae aliquam tempora. Quod ipsa quas eos hic corrupti dignissimos dolorum occaecati. Commodi quis animi at possimus laborum beatae.
                  Aliquam vero suscipit reiciendis dolor placeat. Deleniti corporis tempora accusamus quae nesciunt animi. Numquam occaecati sapiente accusantium amet illum. Vero odio reprehenderit ipsa esse aliquid autem ad.
                default_variant_id: variant_gbHJdmfrXB
                buy_box_variant_id: variant_gbHJdmfrXB
                thumbnail_url:
                tags: []
                price:
                  id: price_gbHJdmfrXB
                  currency: USD
                  amount: '19.99'
                  compare_at_amount:
                  price_list_id:
                  min_quantity: 1
                  variant_id: variant_gbHJdmfrXB
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                original_price:
                seller_id:
                external_references: {}
                status: rejected
                metadata: {}
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivery_profile_id: fp_UkLWZg9DAJ
                seller_name:
                product_type_id:
                tax_category_id: taxcat_UkLWZg9DAJ
                total_on_hand: 0
              schema:
                "$ref": "#/components/schemas/Product"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductRejectParams"
        required: true
  "/api/v3/admin/products/{id}/activate":
    parameters:
    - name: id
      in: path
      required: true
      description: Product ID
      schema:
        type: string
    patch:
      summary: Activate a product
      tags:
      - Products
      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.activate('prod_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api patch /products/{id}/activate -d '{ ... }'
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Puts one product on sale. Runs the activation workflow, so its hooks and the `product.activated` event fire, which `bulk_status_update` does not. A product awaiting review is refused: approve or reject it instead.


        **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: product active
          content:
            application/json:
              example:
                id: prod_gbHJdmfrXB
                name: Product 1674119
                slug: product-1674119
                meta_title:
                meta_description:
                meta_keywords:
                variant_count: 1
                available_on:
                preorder_ships_at:
                purchasable: true
                preorder: false
                in_stock: false
                backorderable: true
                available: true
                description: Tempora doloribus sit consectetur cumque omnis. Quod
                  fugit dicta ullam omnis. Hic dolorem asperiores nemo est sed nihil
                  quia deleniti. Saepe aperiam eos nulla quia porro minima officiis
                  cum. Eius dignissimos laudantium sequi incidunt. Sed nihil voluptate
                  aliquid nisi. Veritatis tenetur quos aspernatur modi perspiciatis
                  quaerat. Voluptas harum neque labore fuga reprehenderit unde quasi.
                  Omnis quam autem in ipsam aspernatur architecto alias recusandae.
                  Repudiandae ratione vel expedita corporis et pariatur rem sapiente.
                  Velit laboriosam nulla quibusdam fugit minus itaque ut repellat.
                  Incidunt est fugiat totam ipsa quod deserunt. Natus sequi numquam
                  laudantium non similique saepe ipsam quos. Ad impedit necessitatibus
                  quo nesciunt blanditiis id similique recusandae. Ut occaecati debitis
                  aliquam accusantium sed distinctio neque. Labore quos quam optio
                  aperiam dolores aspernatur vitae odio. Eius nam adipisci corrupti
                  incidunt quod sapiente tempora dicta.
                description_html: |-
                  Tempora doloribus sit consectetur cumque omnis. Quod fugit dicta ullam omnis. Hic dolorem asperiores nemo est sed nihil quia deleniti.
                  Saepe aperiam eos nulla quia porro minima officiis cum. Eius dignissimos laudantium sequi incidunt. Sed nihil voluptate aliquid nisi.
                  Veritatis tenetur quos aspernatur modi perspiciatis quaerat. Voluptas harum neque labore fuga reprehenderit unde quasi. Omnis quam autem in ipsam aspernatur architecto alias recusandae. Repudiandae ratione vel expedita corporis et pariatur rem sapiente.
                  Velit laboriosam nulla quibusdam fugit minus itaque ut repellat. Incidunt est fugiat totam ipsa quod deserunt. Natus sequi numquam laudantium non similique saepe ipsam quos. Ad impedit necessitatibus quo nesciunt blanditiis id similique recusandae.
                  Ut occaecati debitis aliquam accusantium sed distinctio neque. Labore quos quam optio aperiam dolores aspernatur vitae odio. Eius nam adipisci corrupti incidunt quod sapiente tempora dicta.
                default_variant_id: variant_gbHJdmfrXB
                buy_box_variant_id: variant_gbHJdmfrXB
                thumbnail_url:
                tags: []
                price:
                  id: price_gbHJdmfrXB
                  currency: USD
                  amount: '19.99'
                  compare_at_amount:
                  price_list_id:
                  min_quantity: 1
                  variant_id: variant_gbHJdmfrXB
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                original_price:
                seller_id:
                external_references: {}
                status: active
                metadata: {}
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivery_profile_id: fp_UkLWZg9DAJ
                seller_name:
                product_type_id:
                tax_category_id: taxcat_UkLWZg9DAJ
                total_on_hand: 0
              schema:
                "$ref": "#/components/schemas/Product"
        '422':
          description: the product is awaiting review
          content:
            application/json:
              example:
                error:
                  code: product_in_review
                  message: A product awaiting review is approved or rejected, not
                    moved to another status
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/products/{id}/archive":
    parameters:
    - name: id
      in: path
      required: true
      description: Product ID
      schema:
        type: string
    patch:
      summary: Archive a product
      tags:
      - Products
      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.archive('prod_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api patch /products/{id}/archive -d '{ ... }'
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Takes one product off sale and archives it; activating it puts it back on sale. Runs the archive workflow, so its hooks and its event fire. A product awaiting review is refused: approve or reject it instead.


        **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: product archived
          content:
            application/json:
              example:
                id: prod_gbHJdmfrXB
                name: Product 1714768
                slug: product-1714768
                meta_title:
                meta_description:
                meta_keywords:
                variant_count: 1
                available_on:
                preorder_ships_at:
                purchasable: true
                preorder: false
                in_stock: false
                backorderable: true
                available: false
                description: In exercitationem nobis illo accusamus non quibusdam.
                  Minus corporis commodi magni maxime cumque beatae. Exercitationem
                  provident tempore est corrupti eius at dolor. Rerum delectus id
                  aspernatur consequuntur quod enim. Quis omnis amet inventore alias
                  minima praesentium. Quaerat reprehenderit deleniti atque inventore.
                  Nemo quas nam qui architecto eligendi vel pariatur. Veritatis accusantium
                  molestias deleniti omnis autem modi. Officiis optio quidem iste
                  nihil delectus commodi. Aperiam amet omnis eum praesentium natus
                  recusandae suscipit.
                description_html: |-
                  In exercitationem nobis illo accusamus non quibusdam. Minus corporis commodi magni maxime cumque beatae. Exercitationem provident tempore est corrupti eius at dolor. Rerum delectus id aspernatur consequuntur quod enim.
                  Quis omnis amet inventore alias minima praesentium. Quaerat reprehenderit deleniti atque inventore. Nemo quas nam qui architecto eligendi vel pariatur.
                  Veritatis accusantium molestias deleniti omnis autem modi. Officiis optio quidem iste nihil delectus commodi. Aperiam amet omnis eum praesentium natus recusandae suscipit.
                default_variant_id: variant_gbHJdmfrXB
                buy_box_variant_id: variant_gbHJdmfrXB
                thumbnail_url:
                tags: []
                price:
                  id: price_gbHJdmfrXB
                  currency: USD
                  amount: '19.99'
                  compare_at_amount:
                  price_list_id:
                  min_quantity: 1
                  variant_id: variant_gbHJdmfrXB
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                original_price:
                seller_id:
                external_references: {}
                status: archived
                metadata: {}
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivery_profile_id: fp_UkLWZg9DAJ
                seller_name:
                product_type_id:
                tax_category_id: taxcat_UkLWZg9DAJ
                total_on_hand: 0
              schema:
                "$ref": "#/components/schemas/Product"
        '422':
          description: the product is awaiting review
          content:
            application/json:
              example:
                error:
                  code: product_in_review
                  message: A product awaiting review is approved or rejected, not
                    moved to another status
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/products/{id}/draft":
    parameters:
    - name: id
      in: path
      required: true
      description: Product ID
      schema:
        type: string
    patch:
      summary: Move a product back to draft
      tags:
      - Products
      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.draft('prod_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api patch /products/{id}/draft -d '{ ... }'
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Takes one product off sale, back to a draft. Runs the draft workflow, so its hooks and its event fire. A product awaiting review is refused: approve or reject it instead.


        **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: product draft
          content:
            application/json:
              example:
                id: prod_gbHJdmfrXB
                name: Product 1752527
                slug: product-1752527
                meta_title:
                meta_description:
                meta_keywords:
                variant_count: 1
                available_on:
                preorder_ships_at:
                purchasable: true
                preorder: false
                in_stock: false
                backorderable: true
                available: false
                description: Temporibus fugiat ducimus quae voluptas error. Iure repellat
                  labore aperiam harum magni. Fuga ullam possimus ad repudiandae atque.
                  Excepturi quidem est expedita molestiae delectus. Optio tempora
                  sed minus voluptatum doloremque. Laborum esse voluptate nostrum
                  nesciunt. Ipsum ducimus a dolor nostrum quis corrupti quae illum.
                  Fuga provident deleniti minima ea vel. Cupiditate architecto omnis
                  reprehenderit iusto suscipit corrupti quia cumque. Voluptatem nisi
                  dignissimos aut nostrum distinctio quo explicabo fugiat. Unde minima
                  ratione enim minus officia rerum odio reiciendis. Fugiat perferendis
                  nulla voluptates voluptatum alias. Voluptatem cumque voluptatibus
                  in sint assumenda ad neque. Inventore error consequuntur exercitationem
                  officia consequatur earum iure autem. Odit iure porro reiciendis
                  placeat. Animi minus vel asperiores maiores error tempora. Dolorum
                  esse sapiente voluptatem iste culpa suscipit. Nulla sapiente sit
                  deserunt iste totam dolores. Tempora magni eveniet natus nemo optio.
                  Aliquid quis ullam illo minus. Atque distinctio sapiente voluptatibus
                  adipisci consectetur repellendus culpa dolor. Dolor pariatur tempora
                  ab repellat unde aliquam sequi. Necessitatibus aliquid fugit molestias
                  facilis ratione.
                description_html: |-
                  Temporibus fugiat ducimus quae voluptas error. Iure repellat labore aperiam harum magni. Fuga ullam possimus ad repudiandae atque. Excepturi quidem est expedita molestiae delectus. Optio tempora sed minus voluptatum doloremque.
                  Laborum esse voluptate nostrum nesciunt. Ipsum ducimus a dolor nostrum quis corrupti quae illum. Fuga provident deleniti minima ea vel. Cupiditate architecto omnis reprehenderit iusto suscipit corrupti quia cumque. Voluptatem nisi dignissimos aut nostrum distinctio quo explicabo fugiat.
                  Unde minima ratione enim minus officia rerum odio reiciendis. Fugiat perferendis nulla voluptates voluptatum alias. Voluptatem cumque voluptatibus in sint assumenda ad neque. Inventore error consequuntur exercitationem officia consequatur earum iure autem.
                  Odit iure porro reiciendis placeat. Animi minus vel asperiores maiores error tempora. Dolorum esse sapiente voluptatem iste culpa suscipit. Nulla sapiente sit deserunt iste totam dolores.
                  Tempora magni eveniet natus nemo optio. Aliquid quis ullam illo minus. Atque distinctio sapiente voluptatibus adipisci consectetur repellendus culpa dolor. Dolor pariatur tempora ab repellat unde aliquam sequi. Necessitatibus aliquid fugit molestias facilis ratione.
                default_variant_id: variant_gbHJdmfrXB
                buy_box_variant_id: variant_gbHJdmfrXB
                thumbnail_url:
                tags: []
                price:
                  id: price_gbHJdmfrXB
                  currency: USD
                  amount: '19.99'
                  compare_at_amount:
                  price_list_id:
                  min_quantity: 1
                  variant_id: variant_gbHJdmfrXB
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                original_price:
                seller_id:
                external_references: {}
                status: draft
                metadata: {}
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivery_profile_id: fp_UkLWZg9DAJ
                seller_name:
                product_type_id:
                tax_category_id: taxcat_UkLWZg9DAJ
                total_on_hand: 0
              schema:
                "$ref": "#/components/schemas/Product"
        '422':
          description: the product is awaiting review
          content:
            application/json:
              example:
                error:
                  code: product_in_review
                  message: A product awaiting review is approved or rejected, not
                    moved to another status
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/translations":
    get:
      summary: Translation coverage for a resource type
      tags:
      - Products
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Reports how much of each record is translated into each of the store's non-default locales, plus per-locale totals. A record counts as covered for a locale only when every one of its translatable fields is filled in.

        **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',
          })

          // How much of each product is translated into each of the store's other languages.
          const { data: coverage } = await client.translations.coverage('product', {
            search: 'espresso',
            limit: 25,
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /translations -d '{"search":"espresso","limit":25}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: resource_type
        in: query
        required: true
        description: A translatable resource type, e.g. `product`, `category`, `option_type`.
        schema:
          type: string
      - name: page
        in: query
        required: false
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        schema:
          type: integer
      - name: search
        in: query
        required: false
        description: Free-text term, applied through whichever predicate the resource
          type whitelists (reported back as `search_field`).
        schema:
          type: string
      responses:
        '200':
          description: coverage found
          content:
            application/json:
              example:
                data:
                  resource_type: product
                  default_locale: en
                  locales:
                  - de
                  field_count: 5
                  search_field: name_cont
                  coverage:
                  - locale: de
                    translated: 0
                    total: 1
                    coverage: 0.0
                  records:
                  - id: prod_UkLWZg9DAJ
                    label: Espresso Machine
                    locales:
                      de: 2
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
        '404':
          description: resource type is not translatable
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: record not found
  "/api/v3/admin/policies":
    get:
      summary: List policies
      tags:
      - Policies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the store's policy documents — terms of service, privacy
        policy, returns policy, shipping policy, and any others the merchant
        has written. Every store is created with the four standard policies,
        named but empty.

        A marketplace seller's own policies are managed by the seller and are
        not listed here.


        **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: policies } = await client.policies.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /policies
      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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: fields
        in: query
        required: false
        description: Comma-separated list of fields to include. id is always included.
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `owner_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `owner_type` | Type | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `name`, `owner_id`, `owner_type`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Policy
        sortable:
        - created_at
        - id
        - name
        - owner_id
        - owner_type
        - updated_at
      responses:
        '200':
          description: policies listed
          content:
            application/json:
              example:
                data:
                - id: pol_gbHJdmfrXB
                  name: Privacy Policy
                  slug: privacy-policy
                  body: ''
                  body_html: ''
                  updated_at: '2026-11-11T12:45:25.480Z'
                  created_at: '2026-11-11T12:45:25.480Z'
                - id: pol_uw2YK1rnl0
                  name: Restocking Policy
                  slug: restocking-policy
                  body: Return anything unopened within 30 days.
                  body_html: "<p>Return anything unopened within 30 days.</p>"
                  updated_at: '2026-01-15T12:00:00.000Z'
                  created_at: '2026-01-15T12:00:00.000Z'
                - id: pol_EfhxLZ9ck8
                  name: Returns Policy
                  slug: returns-policy
                  body: ''
                  body_html: ''
                  updated_at: '2026-11-11T12:45:25.483Z'
                  created_at: '2026-11-11T12:45:25.483Z'
                - id: pol_VqXmZF31wY
                  name: Shipping Policy
                  slug: shipping-policy
                  body: ''
                  body_html: ''
                  updated_at: '2026-11-11T12:45:25.486Z'
                  created_at: '2026-11-11T12:45:25.486Z'
                - id: pol_UkLWZg9DAJ
                  name: Terms of Service
                  slug: terms-of-service
                  body: ''
                  body_html: ''
                  updated_at: '2026-11-11T12:45:25.475Z'
                  created_at: '2026-11-11T12:45:25.475Z'
                meta:
                  page: 1
                  limit: 25
                  count: 5
                  pages: 1
                  from: 1
                  to: 5
                  in: 5
                  previous:
                  next:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/Policy"
                  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 policy
      tags:
      - Policies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Creates a policy. `body` accepts HTML and is sanitized before it is
        stored; the stored markup is returned as `body_html`, and `body` reads
        back as plain text.

        The slug is derived from the name when one is not given, and is what
        the storefront addresses the policy by.


        **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 policy = await client.policies.create({
            name: 'Wholesale Policy',
            body: '<p>Trade orders ship within five working days.</p>',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /policies -d '{"name":"Wholesale Policy","body":"<p>Trade
          orders ship within five working days.</p>"}'
      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: policy created
          content:
            application/json:
              example:
                id: pol_OIJLhNcSbf
                name: Wholesale Policy
                slug: wholesale-policy
                body: Trade orders ship within five working days.
                body_html: "<p>Trade orders ship within five working days.</p>"
                updated_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/Policy"
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PolicyCreateParams"
        required: true
  "/api/v3/admin/policies/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Policy prefixed ID or slug
      schema:
        type: string
    get:
      summary: Get a policy
      tags:
      - Policies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a single policy, addressed by prefixed ID or by slug.

        **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',
          })

          // Addressable by slug as well as prefixed id.
          const policy = await client.policies.get('returns-policy')
      - lang: bash
        label: Spree CLI
        source: spree api get /policies/{id}
      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: policy found
          content:
            application/json:
              example:
                id: pol_uw2YK1rnl0
                name: Restocking Policy
                slug: restocking-policy
                body: Return anything unopened within 30 days.
                body_html: "<p>Return anything unopened within 30 days.</p>"
                updated_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/Policy"
        '404':
          description: policy not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Policy not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update a policy
      tags:
      - Policies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Updates a policy. `body` accepts HTML and is sanitized before it is stored.

        **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 policy = await client.policies.update('returns-policy', {
            body: '<p>Return anything unopened within 60 days.</p>',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /policies/{id} -d '{"body":"<p>Return anything unopened
          within 60 days.</p>"}'
      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: policy updated
          content:
            application/json:
              example:
                id: pol_uw2YK1rnl0
                name: Restocking Policy
                slug: restocking-policy
                body: Return anything unopened within 60 days.
                body_html: "<p>Return anything unopened within 60 days.</p>"
                updated_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/Policy"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PolicyUpdateParams"
        required: true
    delete:
      summary: Delete a policy
      tags:
      - Policies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Deletes a policy. The four policies a store is created with can be
        deleted like any other — they are conventions, not fixtures.


        **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.policies.delete('wholesale-policy')
      - lang: bash
        label: Spree CLI
        source: spree api delete /policies/{id}
      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: policy deleted
  "/api/v3/admin/claim_reasons":
    get:
      summary: List claim reasons
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Why a customer raised a claim — what the merchant got wrong, rather than a change of mind.

        The vocabulary is the merchant's own — seeded with a starting set and
        edited from the dashboard. Inactive rows stay for the records that
        already reference them, but are not offered on new ones.


        **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: reasons } = await client.claimReasons.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /claim_reasons
      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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: sort
        in: query
        required: false
        description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`).
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `active` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `active`, `created_at`, `id`, `name`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: ClaimReason
        sortable:
        - active
        - created_at
        - id
        - name
        - updated_at
      responses:
        '200':
          description: claim reasons found
          content:
            application/json:
              example:
                data:
                - id: clr_UkLWZg9DAJ
                  name: Arrived damaged
                  active: true
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  can_be_deleted: true
                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 claim reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds a claim reason to this store. Names are unique per store, ignoring case.

        **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 reason = await client.claimReasons.create({
            name: 'Arrived damaged',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /claim_reasons -d '{"name":"Arrived damaged"}'
      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: claim reason created
          content:
            application/json:
              example:
                id: clr_gbHJdmfrXB
                name: A new reason
                active: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                can_be_deleted: true
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReasonCreateParams"
        required: true
  "/api/v3/admin/claim_reasons/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Claim reason ID
      schema:
        type: string
    get:
      summary: Get a claim reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a single claim reason 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 reason = await client.claimReasons.get('clr_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /claim_reasons/{id}
      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: claim reason found
          content:
            application/json:
              example:
                id: clr_UkLWZg9DAJ
                name: Arrived damaged
                active: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                can_be_deleted: true
        '404':
          description: claim reason not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Claim reason not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update a claim reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Renames a claim reason or retires it. Deactivating keeps it on the records
        that already carry it while removing it from the pickers.


        **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 reason = await client.claimReasons.update('clr_UkLWZg9DAJ', {
            active: false,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /claim_reasons/{id} -d '{"active":false}'
      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: claim reason updated
          content:
            application/json:
              example:
                id: clr_UkLWZg9DAJ
                name: Arrived damaged
                active: false
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                can_be_deleted: true
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReasonUpdateParams"
        required: true
    delete:
      summary: Delete a claim reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Removes a claim reason the store no longer uses. A reason already recorded
        on a document is refused — deactivate it instead, so the history it
        explains stays readable.


        **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.claimReasons.delete('clr_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /claim_reasons/{id}
      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: claim reason deleted
  "/api/v3/admin/order_cancellation_reasons":
    get:
      summary: List order cancellation reasons
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Why an order was called off before it shipped. Staff pick one when canceling.

        The vocabulary is the merchant's own — seeded with a starting set and
        edited from the dashboard. Inactive rows stay for the records that
        already reference them, but are not offered on new ones.


        **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: reasons } = await client.orderCancellationReasons.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /order_cancellation_reasons
      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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: sort
        in: query
        required: false
        description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`).
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `active` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `active`, `created_at`, `id`, `name`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: OrderCancellationReason
        sortable:
        - active
        - created_at
        - id
        - name
        - updated_at
      responses:
        '200':
          description: order cancellation reasons found
          content:
            application/json:
              example:
                data:
                - id: ocr_UkLWZg9DAJ
                  name: Out of stock
                  active: true
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  can_be_deleted: true
                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 order cancellation reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds a order cancellation reason to this store. Names are unique per store, ignoring case.

        **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 reason = await client.orderCancellationReasons.create({
            name: 'Out of stock',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /order_cancellation_reasons -d '{"name":"Out of stock"}'
      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 cancellation reason created
          content:
            application/json:
              example:
                id: ocr_gbHJdmfrXB
                name: A new reason
                active: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                can_be_deleted: true
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReasonCreateParams"
        required: true
  "/api/v3/admin/order_cancellation_reasons/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Order cancellation reason ID
      schema:
        type: string
    get:
      summary: Get a order cancellation reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a single order cancellation reason 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 reason = await client.orderCancellationReasons.get('ocr_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /order_cancellation_reasons/{id}
      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: order cancellation reason found
          content:
            application/json:
              example:
                id: ocr_UkLWZg9DAJ
                name: Out of stock
                active: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                can_be_deleted: true
        '404':
          description: order cancellation reason not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Order cancellation reason not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update a order cancellation reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Renames a order cancellation reason or retires it. Deactivating keeps it on the records
        that already carry it while removing it from the pickers.


        **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 reason = await client.orderCancellationReasons.update('ocr_UkLWZg9DAJ', {
            active: false,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /order_cancellation_reasons/{id} -d '{"active":false}'
      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: order cancellation reason updated
          content:
            application/json:
              example:
                id: ocr_UkLWZg9DAJ
                name: Out of stock
                active: false
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                can_be_deleted: true
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReasonUpdateParams"
        required: true
    delete:
      summary: Delete a order cancellation reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Removes a order cancellation reason the store no longer uses. A reason already recorded
        on a document is refused — deactivate it instead, so the history it
        explains stays readable.


        **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.orderCancellationReasons.delete('ocr_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /order_cancellation_reasons/{id}
      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: order cancellation reason deleted
  "/api/v3/admin/refund_reasons":
    get:
      summary: List refund reasons
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Why money went back. Some rows are seeded and looked up by name, so they refuse renaming and deletion.

        The vocabulary is the merchant's own — seeded with a starting set and
        edited from the dashboard. Inactive rows stay for the records that
        already reference them, but are not offered on new ones.


        **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: reasons } = await client.refundReasons.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /refund_reasons
      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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: sort
        in: query
        required: false
        description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`).
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `active` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `active`, `created_at`, `id`, `name`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: RefundReason
        sortable:
        - active
        - created_at
        - id
        - name
        - updated_at
      responses:
        '200':
          description: refund reasons found
          content:
            application/json:
              example:
                data:
                - id: rr_UkLWZg9DAJ
                  name: Goodwill gesture
                  active: true
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  can_be_deleted: true
                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 refund reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds a refund reason to this store. Names are unique per store, ignoring case.

        **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 reason = await client.refundReasons.create({
            name: 'Goodwill gesture',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /refund_reasons -d '{"name":"Goodwill gesture"}'
      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: refund reason created
          content:
            application/json:
              example:
                id: rr_gbHJdmfrXB
                name: A new reason
                active: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                can_be_deleted: true
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReasonCreateParams"
        required: true
  "/api/v3/admin/refund_reasons/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Refund reason ID
      schema:
        type: string
    get:
      summary: Get a refund reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a single refund reason 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 reason = await client.refundReasons.get('rr_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /refund_reasons/{id}
      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: refund reason found
          content:
            application/json:
              example:
                id: rr_UkLWZg9DAJ
                name: Goodwill gesture
                active: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                can_be_deleted: true
        '404':
          description: refund reason not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Refund reason not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update a refund reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Renames a refund reason or retires it. Deactivating keeps it on the records
        that already carry it while removing it from the pickers.


        **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 reason = await client.refundReasons.update('rr_UkLWZg9DAJ', {
            active: false,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /refund_reasons/{id} -d '{"active":false}'
      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: refund reason updated
          content:
            application/json:
              example:
                id: rr_UkLWZg9DAJ
                name: Goodwill gesture
                active: false
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                can_be_deleted: true
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReasonUpdateParams"
        required: true
    delete:
      summary: Delete a refund reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Removes a refund reason the store no longer uses. A reason already recorded
        on a document is refused — deactivate it instead, so the history it
        explains stays readable.


        **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.refundReasons.delete('rr_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /refund_reasons/{id}
      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: refund reason deleted
  "/api/v3/admin/return_reasons":
    get:
      summary: List return reasons
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Why a customer is sending items back. Shared by returns and exchanges.

        The vocabulary is the merchant's own — seeded with a starting set and
        edited from the dashboard. Inactive rows stay for the records that
        already reference them, but are not offered on new ones.


        **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: reasons } = await client.returnReasons.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /return_reasons
      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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: sort
        in: query
        required: false
        description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`).
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `active` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `active`, `created_at`, `id`, `name`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: ReturnReason
        sortable:
        - active
        - created_at
        - id
        - name
        - updated_at
      responses:
        '200':
          description: return reasons found
          content:
            application/json:
              example:
                data:
                - id: rar_UkLWZg9DAJ
                  name: Damaged in transit
                  active: true
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  can_be_deleted: true
                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 return reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds a return reason to this store. Names are unique per store, ignoring case.

        **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 reason = await client.returnReasons.create({
            name: 'Damaged in transit',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /return_reasons -d '{"name":"Damaged in transit"}'
      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: return reason created
          content:
            application/json:
              example:
                id: rar_gbHJdmfrXB
                name: A new reason
                active: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                can_be_deleted: true
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReasonCreateParams"
        required: true
  "/api/v3/admin/return_reasons/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Return reason ID
      schema:
        type: string
    get:
      summary: Get a return reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a single return reason 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 reason = await client.returnReasons.get('rar_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /return_reasons/{id}
      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: return reason found
          content:
            application/json:
              example:
                id: rar_UkLWZg9DAJ
                name: Damaged in transit
                active: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                can_be_deleted: true
        '404':
          description: return reason not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Return reason not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update a return reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Renames a return reason or retires it. Deactivating keeps it on the records
        that already carry it while removing it from the pickers.


        **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 reason = await client.returnReasons.update('rar_UkLWZg9DAJ', {
            active: false,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /return_reasons/{id} -d '{"active":false}'
      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: return reason updated
          content:
            application/json:
              example:
                id: rar_UkLWZg9DAJ
                name: Damaged in transit
                active: false
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                can_be_deleted: true
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReasonUpdateParams"
        required: true
    delete:
      summary: Delete a return reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Removes a return reason the store no longer uses. A reason already recorded
        on a document is refused — deactivate it instead, so the history it
        explains stays readable.


        **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.returnReasons.delete('rar_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /return_reasons/{id}
      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: return reason deleted
  "/api/v3/admin/tax_exemption_reasons":
    get:
      summary: List tax exemption reasons
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Why a business buys without tax — the reasons a merchant can record on a
        tax exemption certificate. Each has the merchant's own `name` and a `code`,
        which certificates record and the tax provider receives.

        The vocabulary is the merchant's own — seeded with a starting set and
        edited from the dashboard. A provider whose engine reads the code lists
        the codes it understands on `GET /tax_providers`. Inactive rows stay on the
        certificates that already record them, but are not offered on new ones.


        **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: reasons } = await client.taxExemptionReasons.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /tax_exemption_reasons
      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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: sort
        in: query
        required: false
        description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`).
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `active` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `active`, `code`, `created_at`, `id`, `name`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: TaxExemptionReason
        sortable:
        - active
        - code
        - created_at
        - id
        - name
        - updated_at
      responses:
        '200':
          description: tax exemption reasons found
          content:
            application/json:
              example:
                data:
                - id: txr_UkLWZg9DAJ
                  name: Reseller (wholesale)
                  code: G
                  active: true
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  can_be_deleted: true
                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 tax exemption reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds a tax exemption reason to this store. Names and codes are unique per 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',
          })

          // `code` is what certificates record and the tax engine receives — on
          // Avalara, an entity use code such as `G` (resale).
          const reason = await client.taxExemptionReasons.create({
            name: 'Reseller (wholesale)',
            code: 'G',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /tax_exemption_reasons -d '{"name":"Reseller (wholesale)","code":"G"}'
      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: tax exemption reason created
          content:
            application/json:
              example:
                id: txr_gbHJdmfrXB
                name: Federal government
                code: A
                active: true
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                can_be_deleted: true
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank and Code can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
                    code:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaxExemptionReasonCreateParams"
        required: true
  "/api/v3/admin/tax_exemption_reasons/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Tax exemption reason ID
      schema:
        type: string
    get:
      summary: Get a tax exemption reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a single tax exemption reason 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 reason = await client.taxExemptionReasons.get('txr_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /tax_exemption_reasons/{id}
      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: tax exemption reason found
          content:
            application/json:
              example:
                id: txr_UkLWZg9DAJ
                name: Reseller (wholesale)
                code: G
                active: true
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                can_be_deleted: true
        '404':
          description: tax exemption reason not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Tax exemption reason not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update a tax exemption reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Renames a tax exemption reason or retires it. Deactivating keeps it on the
        certificates that already record it while removing it from the pickers. The
        code can change at any time, and every certificate holding the reason sends
        the new code to the tax provider from then on.


        **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 reason = await client.taxExemptionReasons.update('txr_UkLWZg9DAJ', {
            active: false,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /tax_exemption_reasons/{id} -d '{"active":false}'
      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: tax exemption reason updated
          content:
            application/json:
              example:
                id: txr_UkLWZg9DAJ
                name: Reseller (wholesale)
                code: G
                active: false
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                can_be_deleted: true
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaxExemptionReasonUpdateParams"
        required: true
    delete:
      summary: Delete a tax exemption reason
      tags:
      - Reasons
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Removes a tax exemption reason the store no longer uses. A reason a
        certificate records is refused — deactivate it instead.


        **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.taxExemptionReasons.delete('txr_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /tax_exemption_reasons/{id}
      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: tax exemption reason deleted
        '422':
          description: tax exemption reason is in use
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Tax exemption reason cannot be deleted
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /promotions/{promotion_id}/coupon_codes
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[code_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `promotion_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `state` | One of `unused`, `used` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[promotion_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `promotion_` | `code`, `created_at`, `expires_at`, `id`, `kind`, `name`, `path`, `promotion_category_id`, `starts_at`, `updated_at` |

          </Accordion>

          **Sort by:** `code`, `created_at`, `id`, `promotion_id`, `state`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CouponCode
        sortable:
        - code
        - created_at
        - id
        - promotion_id
        - state
        - updated_at
      responses:
        '200':
          description: coupon codes found
          content:
            application/json:
              example:
                data:
                - id: coupon_UkLWZg9DAJ
                  code: AAA111
                  state: unused
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  promotion_id: promo_UkLWZg9DAJ
                  order_id:
                - id: coupon_gbHJdmfrXB
                  code: BBB222
                  state: unused
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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}/custom_fields":
    get:
      summary: List promotion custom fields
      tags:
      - Promotions
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the promotion's custom field values.

        **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: customFields } = await client.customFields('promotion', 'promo_UkLWZg9DAJ').list()
      - lang: bash
        label: Spree CLI
        source: spree api get /promotions/{promotion_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: promotion_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /promotions/{promotion_id}/promotion_actions
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `position`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: PromotionAction
        sortable:
        - created_at
        - id
        - position
        - updated_at
      responses:
        '200':
          description: actions found
          content:
            application/json:
              example:
                data:
                - id: pact_UkLWZg9DAJ
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  type: free_shipping
                  promotion_id: promo_UkLWZg9DAJ
                  preferences: {}
                  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`).

        **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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /promotions/{promotion_id}/promotion_actions -d '{"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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: free_shipping
                promotion_id: promo_UkLWZg9DAJ
                preferences: {}
                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:
              "$ref": "#/components/schemas/PromotionActionCreateParams"
        required: true
  "/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
    patch:
      summary: Update an action on a promotion
      tags:
      - Promotions
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Changes an action's settings. For adjustment actions, `calculator`
        sets the calculator and its preferences; sending a different
        calculator `type` swaps it. The action's own `type` is fixed once
        created.


        **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.update('promo_UkLWZg9DAJ', 'pact_k5nR8xLqPz', {
            calculator: { type: 'percent_on_line_item', preferences: { percent: '15' } },
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /promotions/{promotion_id}/promotion_actions/{id}
          -d '{"calculator":{"type":"percent_on_line_item","preferences":{"percent":"15"}}}'
      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 updated
          content:
            application/json:
              example:
                id: pact_UkLWZg9DAJ
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: create_item_adjustments
                promotion_id: promo_UkLWZg9DAJ
                preferences: {}
                calculator:
                  type: percent_on_line_item
                  preferences:
                    percent: '15.0'
                    apply_only_on_full_priced_items: false
                line_items:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PromotionActionUpdateParams"
        required: true
    delete:
      summary: Delete an action from a promotion
      tags:
      - Promotions
      security:
      - api_key: []
        bearer_auth: []
      description: "**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',
          })

          await client.promotions.actions.delete('promo_UkLWZg9DAJ', 'promoact_k5nR8xLq')
      - lang: bash
        label: Spree CLI
        source: spree api delete /promotions/{promotion_id}/promotion_actions/{id}
      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')
      - lang: bash
        label: Spree CLI
        source: spree api get /promotions/{promotion_id}/promotion_rules
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: PromotionRule
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: rules found
          content:
            application/json:
              example:
                data:
                - id: prorule_UkLWZg9DAJ
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  type: currency
                  promotion_id: promo_UkLWZg9DAJ
                  preferences:
                    currency: USD
                  product_ids:
                  category_ids:
                  customer_ids:
                  option_value_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`).

        **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' },
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /promotions/{promotion_id}/promotion_rules -d '{"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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: currency
                promotion_id: promo_UkLWZg9DAJ
                preferences:
                  currency: EUR
                product_ids:
                category_ids:
                customer_ids:
                option_value_ids:
        '422':
          description: unknown rule type
          content:
            application/json:
              example:
                error:
                  code: unknown_promotion_rule_type
                  message: Unknown type
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PromotionRuleCreateParams"
        required: true
  "/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)."
      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.update('promo_UkLWZg9DAJ', 'promorule_k5nR8xLq', {
            preferences: { currency: 'USD' },
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /promotions/{promotion_id}/promotion_rules/{id} -d
          '{"preferences":{"currency":"USD"}}'
      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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: currency
                promotion_id: promo_UkLWZg9DAJ
                preferences:
                  currency: GBP
                product_ids:
                category_ids:
                customer_ids:
                option_value_ids:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PromotionRuleUpdateParams"
        required: 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)."
      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.promotions.rules.delete('promo_UkLWZg9DAJ', 'promorule_k5nR8xLq')
      - lang: bash
        label: Spree CLI
        source: spree api delete /promotions/{promotion_id}/promotion_rules/{id}
      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()
      - lang: bash
        label: Spree CLI
        source: spree api get /promotions
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name and code (partial, case-insensitive).
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `expires_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `kind` | One of `coupon_code`, `automatic` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `path` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `promotion_category_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `starts_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[coupon_codes_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `coupon_codes_` | `code`, `created_at`, `id`, `promotion_id`, `state`, `updated_at` |

          </Accordion>

          **Sort by:** `code`, `created_at`, `expires_at`, `id`, `kind`, `name`, `path`, `promotion_category_id`, `starts_at`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Promotion
        sortable:
        - code
        - created_at
        - expires_at
        - id
        - kind
        - name
        - path
        - promotion_category_id
        - starts_at
        - updated_at
      responses:
        '200':
          description: promotions found
          content:
            application/json:
              example:
                data:
                - id: promo_UkLWZg9DAJ
                  name: Summer Sale
                  description:
                  code: summer
                  starts_at: '2026-01-15T11:00:00.000Z'
                  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-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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.00', 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' },
            ],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /promotions -d '{"name":"Black Friday","code":"BLACKFRIDAY","starts_at":"2026-11-29T00:00:00Z","expires_at":"2026-12-01T00:00:00Z"}'
      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-01-15T12:00:00.000Z'
                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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                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:
                    - code: blank
                      message: can't be blank
                      specific: false
                    code:
                    - code: blank
                      message: can't be blank
                      specific: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PromotionCreateParams"
        required: true
  "/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)."
      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 promotion = await client.promotions.get('promo_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /promotions/{id}
      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: `rules`, `actions` (each
          under the same shape the write accepts), `custom_fields`.'
        schema:
          type: string
      responses:
        '200':
          description: promotion found
          content:
            application/json:
              example:
                id: promo_UkLWZg9DAJ
                name: Summer Sale
                description:
                code: summer
                starts_at: '2026-01-15T11:00:00.000Z'
                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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                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.00', 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: [],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /promotions/{id} -d '{"description":"Updated description"}'
      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-01-15T11:00:00.000Z'
                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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                action_ids: []
                rule_ids: []
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PromotionUpdateParams"
        required: true
    delete:
      summary: Delete a promotion
      tags:
      - Promotions
      security:
      - api_key: []
        bearer_auth: []
      description: "**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',
          })

          await client.promotions.delete('promo_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /promotions/{id}
      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()
      - lang: bash
        label: Spree CLI
        source: spree api get /promotion_actions/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: Adds the specified quantity of a variant to the cart
                    free of charge
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: create_item_adjustments
                  label: Create per-line-item adjustment
                  description: Creates a promotion credit adjustment on a line item
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: create_adjustment
                  label: Create whole-order adjustment
                  description: Creates a promotion credit adjustment on the order
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: free_shipping
                  label: Free shipping
                  description: Makes all shipments for the order free
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
  "/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()
      - lang: bash
        label: Spree CLI
        source: spree api get /promotion_rules/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: Order includes products in specified categories
                  schema:
                    type: object
                    properties:
                      match_policy:
                        type: string
                        enum:
                        - any
                        - all
                        default: any
                    additionalProperties: false
                - type: channel
                  label: Channel(s)
                  description: Limit to orders placed through specified channel(s)
                  schema:
                    type: object
                    properties:
                      channel_ids:
                        type: array
                        items:
                          type: string
                          format: prefixed-id
                          pattern: "^ch_[A-Za-z0-9]+$"
                          x-spree-prefix: ch
                        default: []
                    additionalProperties: false
                - type: country
                  label: Country
                  description: Limit to orders with shipping address in a specific
                    country
                  schema:
                    type: object
                    properties:
                      country_codes:
                        type: array
                        items:
                          type: string
                          format: iso-country
                          pattern: "^[A-Z]{2}$"
                        default: []
                      country_id:
                        type:
                        - integer
                        - 'null'
                      country_code:
                        type:
                        - string
                        - 'null'
                        format: iso-country
                        pattern: "^[A-Z]{2}$"
                    additionalProperties: false
                - type: currency
                  label: Currency
                  description: Limit to orders in a specific currency
                  schema:
                    type: object
                    properties:
                      currency:
                        type:
                        - string
                        - 'null'
                        format: currency
                        pattern: "^[A-Z]{3}$"
                    additionalProperties: false
                - type: customer_group
                  label: Customer Group(s)
                  description: Available only to customers in specified customer group(s)
                  schema:
                    type: object
                    properties:
                      customer_group_ids:
                        type: array
                        items:
                          type: string
                          format: prefixed-id
                          pattern: "^cg_[A-Za-z0-9]+$"
                          x-spree-prefix: cg
                        default: []
                    additionalProperties: false
                - type: customer
                  label: Customers
                  description: Available only to the specified customers
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: first_order
                  label: First order
                  description: Must be the customer's first order
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: item_total
                  label: Item total
                  description: Order total meets these criteria
                  schema:
                    type: object
                    properties:
                      amount_min:
                        type: string
                        format: money
                        pattern: "^-?\\d+(\\.\\d+)?$"
                        default: '100'
                      operator_min:
                        type: string
                        default: ">"
                      amount_max:
                        type:
                        - string
                        - 'null'
                        format: money
                        pattern: "^-?\\d+(\\.\\d+)?$"
                      operator_max:
                        type: string
                        default: "<"
                    additionalProperties: false
                - type: market
                  label: Market(s)
                  description: Limit to orders placed in specified market(s)
                  schema:
                    type: object
                    properties:
                      market_ids:
                        type: array
                        items:
                          type: string
                          format: prefixed-id
                          pattern: "^mkt_[A-Za-z0-9]+$"
                          x-spree-prefix: mkt
                        default: []
                    additionalProperties: false
                - type: one_use_per_user
                  label: One Use Per User
                  description: Only One Use Per User
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: customer_logged_in
                  label: Only logged in customers
                  description: Available only to logged in customers
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: option_value
                  label: Option Value(s)
                  description: Order includes products with matching option value(s)
                  schema:
                    type: object
                    properties:
                      match_policy:
                        type: string
                        enum:
                        - any
                        default: any
                      eligible_values:
                        type: array
                        items:
                          type: string
                          format: prefixed-id
                          pattern: "^optval_[A-Za-z0-9]+$"
                          x-spree-prefix: optval
                        default: []
                    additionalProperties: false
                - type: product
                  label: Product(s)
                  description: Order includes specified product(s)
                  schema:
                    type: object
                    properties:
                      match_policy:
                        type: string
                        enum:
                        - any
                        - all
                        - none
                        default: any
                    additionalProperties: false
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/refunds
      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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Refund
        sortable:
        - created_at
        - id
        - updated_at
      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: 'rr_UkLWZg9DAJ',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{order_id}/refunds -d '{"payment_id":"pay_UkLWZg9DAJ","amount":"5.00","refund_reason_id":"rr_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-c5ae59a82a25
                amount: '5.00'
                payment_id: py_UkLWZg9DAJ
                refund_reason_id: rr_UkLWZg9DAJ
                originator_id:
                originator_type:
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                tax_amount: '0.00'
                refunder_id: adm_UkLWZg9DAJ
                refunder_type: admin_user
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/RefundCreateParams"
        required: true
  "/api/v3/admin/tax_rates/{tax_rate_id}/custom_fields":
    get:
      summary: List tax rate custom fields
      tags:
      - Settings
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the tax rate's custom field values.

        **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: customFields } = await client.customFields('tax_rate', 'tax_UkLWZg9DAJ').list()
      - lang: bash
        label: Spree CLI
        source: spree api get /tax_rates/{tax_rate_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: tax_rate_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/stores/{store_id}/custom_fields":
    get:
      summary: List store custom fields
      tags:
      - Settings
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the store's custom field values.

        **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: customFields } = await client.customFields('store', 'store_UkLWZg9DAJ').list()
      - lang: bash
        label: Spree CLI
        source: spree api get /stores/{store_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: store_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/diagnostics":
    get:
      summary: Get the diagnostics report
      tags:
      - Settings
      security:
      - bearer_auth: []
      description: |
        An anonymised description of this installation to attach to a bug
        report: Spree and gem versions, runtime and infrastructure, settings
        changed from their defaults, and recent Spree errors by class and code
        location. It never contains names, emails, URLs, credentials or error
        messages. `markdown` is the same report ready to paste into a GitHub
        issue. Available to signed-in admins who can manage the store; a
        secret API key gets a 404.
      x-codeSamples:
      - lang: javascript
        label: Spree Admin SDK
        source: |-
          import { createAdminClient } from '@spree/admin-sdk'

          const client = createAdminClient({
            baseUrl: 'https://your-store.com',
            jwtToken: 'eyJhbGciOi...',
          })

          // Needs a client created with `jwtToken`: a secret key is refused.
          const report = await client.diagnostics.get()
          console.log(report.markdown)
      parameters:
      - name: Authorization
        in: header
        required: true
        description: Bearer token for admin authentication
        schema:
          type: string
      - name: packages
        in: query
        required: false
        description: The caller's own `@spree/*` packages as comma-separated `name@version`,
          reported in a Dashboard section. Other entries are ignored.
        example: "@spree/dashboard@6.0.4,@spree/admin-sdk@6.0.4"
        schema:
          type: string
      responses:
        '200':
          description: diagnostics report
          content:
            application/json:
              example:
                spree_version: 6.0.3
                sections:
                - key: platform
                  title: Spree
                  rows:
                  - label: Version
                    value: 6.0.3
                  - label: Gems
                    value: spree_api 6.0.3, spree_core 6.0.3
                  - label: Other gems built on Spree
                    value: '0'
                - key: runtime
                  title: Runtime
                  rows:
                  - label: Ruby
                    value: 4.0.9 (arm64-darwin25)
                  - label: Rails
                    value: 8.1.4.1
                  - label: Environment
                    value: test
                  - label: Operating system
                    value: Linux 6.8.0 x86_64
                  - label: Web server
                    value: Puma 8.0.2
                - key: infrastructure
                  title: Infrastructure
                  rows:
                  - label: Database
                    value: sqlite3 3.54.1
                  - label: Queue adapter
                    value: test
                  - label: Cache store
                    value: null_store
                  - label: File storage
                    value: test
                - key: preferences
                  title: Changed settings
                  rows: []
                - key: dashboard
                  title: Dashboard
                  rows:
                  - label: "@spree/dashboard"
                    value: 6.0.4
                errors: []
                generated_at: '2026-01-15T12:00:00.000Z'
                markdown: |-
                  <details>
                  <summary>Spree 6.0.3 diagnostics (2026-01-15T12:00:00Z)</summary>

                  **Spree**

                  | | |
                  | --- | --- |
                  | Version | 6.0.3 |
                  | Gems | spree_api 6.0.3, spree_core 6.0.3 |
                  | Other gems built on Spree | 0 |

                  **Runtime**

                  | | |
                  | --- | --- |
                  | Ruby | 4.0.9 (arm64-darwin25) |
                  | Rails | 8.1.4.1 |
                  | Environment | test |
                  | Operating system | Linux 6.8.0 x86_64 |
                  | Web server | Puma 8.0.2 |

                  **Infrastructure**

                  | | |
                  | --- | --- |
                  | Database | sqlite3 3.54.1 |
                  | Queue adapter | test |
                  | Cache store | null_store |
                  | File storage | test |

                  **Dashboard**

                  | | |
                  | --- | --- |
                  | @spree/dashboard | 6.0.4 |

                  **Recent errors**

                  None recorded.

                  </details>
                issue_url: https://github.com/spree/spree/issues/new?template=bug_report.yml&environment=%3Cdetails%3E%0A%3Csummary%3ESpree%206.0.3%20diagnostics%20%282026-01-15T12%3A00%3A00Z%29%3C%2Fsummary%3E%0A%0A%2A%2ASpree%2A%2A%0A%0A%7C%20%7C%20%7C%0A%7C%20---%20%7C%20---%20%7C%0A%7C%20Version%20%7C%206.0.3%20%7C%0A%7C%20Gems%20%7C%20spree_api%206.0.3%2C%20spree_core%206.0.3%20%7C%0A%7C%20Other%20gems%20built%20on%20Spree%20%7C%200%20%7C%0A%0A%2A%2ARuntime%2A%2A%0A%0A%7C%20%7C%20%7C%0A%7C%20---%20%7C%20---%20%7C%0A%7C%20Ruby%20%7C%204.0.9%20%28arm64-darwin25%29%20%7C%0A%7C%20Rails%20%7C%208.1.4.1%20%7C%0A%7C%20Environment%20%7C%20test%20%7C%0A%7C%20Operating%20system%20%7C%20Linux%206.8.0%20x86_64%20%7C%0A%7C%20Web%20server%20%7C%20Puma%208.0.2%20%7C%0A%0A%2A%2AInfrastructure%2A%2A%0A%0A%7C%20%7C%20%7C%0A%7C%20---%20%7C%20---%20%7C%0A%7C%20Database%20%7C%20sqlite3%203.54.1%20%7C%0A%7C%20Queue%20adapter%20%7C%20test%20%7C%0A%7C%20Cache%20store%20%7C%20null_store%20%7C%0A%7C%20File%20storage%20%7C%20test%20%7C%0A%0A%2A%2ADashboard%2A%2A%0A%0A%7C%20%7C%20%7C%0A%7C%20---%20%7C%20---%20%7C%0A%7C%20%40spree%2Fdashboard%20%7C%206.0.4%20%7C%0A%0A%2A%2ARecent%20errors%2A%2A%0A%0ANone%20recorded.%0A%0A%3C%2Fdetails%3E
                issue_prefilled: true
              schema:
                "$ref": "#/components/schemas/Diagnostics"
        '401':
          description: unauthorized
          content:
            application/json:
              example:
                error:
                  code: authentication_required
                  message: Authentication required
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/locales":
    get:
      summary: List supported locales
      tags:
      - Settings
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the locales a merchant can translate content into for the current store, with the default and right-to-left flags.

        **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 locales = await client.locales.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /locales
      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: locales found
          content:
            application/json:
              example:
                data:
                - code: de
                  default: false
                  rtl: false
                - code: en
                  default: true
                  rtl: false
                - code: fr
                  default: false
                  rtl: false
  "/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()
      - lang: bash
        label: Spree CLI
        source: spree api get /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: current store
          content:
            application/json:
              example:
                id: store_UkLWZg9DAJ
                name: Spree Test Store
                seo_title:
                meta_description: Sample store description.
                metadata: {}
                code: spree_1
                default_currency: USD
                default_locale: en
                default_country_code: US
                mail_from_address: no-reply@example.com
                customer_support_email: support@example.com
                new_order_notifications_email: store-owner@example.com
                created_at: '2026-11-11T12:45:25.412Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                order_routing_strategy: rules
                payout_provider:
                admin_locale:
                timezone: UTC
                storefront_url:
                weight_unit: lb
                unit_system: imperial
                storefront_access: public
                guest_checkout: true
                always_include_confirm_step: false
                company_field_enabled: false
                address_requires_company: false
                address_requires_phone: false
                capture_method: checkout
                track_inventory_levels: true
                stock_reservations_enabled: true
                low_stock_threshold: 5
                tax_using_ship_address: true
                track_price_history: true
                show_products_without_price: false
                disable_sku_validation: false
                pricing_provider: internal
                inventory_provider: internal
                pricing_provider_failure_policy: strict
                inventory_provider_failure_policy: fallback
                default_payouts_schedule_interval: monthly
                auto_approve_sellers: false
                auto_approve_seller_products: false
                seller_digital_assets_enabled: false
                seller_digital_asset_content_types:
                - application/pdf
                - application/epub+zip
                - application/zip
                - application/x-7z-compressed
                - application/gzip
                - application/json
                - text/plain
                - text/csv
                - audio/mpeg
                - audio/mp4
                - audio/aac
                - audio/flac
                - audio/ogg
                - audio/wav
                - audio/x-wav
                - audio/midi
                - video/mp4
                - video/webm
                - video/quicktime
                - image/jpeg
                - image/png
                - image/gif
                - image/webp
                - image/tiff
                review_seller_digital_asset_changes: true
                send_seller_transactional_emails: true
                document_number_format: sequential
                order_number_prefix: R
                order_number_suffix: ''
                order_number_sequence_start: 1001
                limit_digital_download_count: true
                digital_asset_authorized_clicks: 5
                limit_digital_download_days: true
                digital_asset_authorized_days: 7
                send_consumer_transactional_emails: true
                email_accent_color:
                email_background_color:
                email_card_color:
                email_text_color:
                email_heading_color:
                email_font:
                order_number_sequence_started: false
                default_minimum_payout_amount: '0.00'
                default_commission_tax_rate: '0'
                url: http://www.example.com:3000
                api_url: http://www.example.com:3000
                setup_tasks:
                - name: setup_address
                  done: false
                - name: setup_payment_method
                  done: false
                - name: add_products
                  done: false
                - name: set_customer_support_email
                  done: true
                - name: setup_taxes_collection
                  done: false
                - name: setup_storefront
                  done: false
                supported_currencies:
                - USD
                - EUR
                - GBP
                supported_locales:
                - en
                available_locales:
                - aa
                - ab
                - ae
                - af
                - ak
                - am
                - an
                - ar
                - as
                - av
                - ay
                - az
                - ba
                - be
                - bg
                - bh
                - bi
                - bm
                - bn
                - bo
                - br
                - bs
                - ca
                - ce
                - ch
                - co
                - cr
                - cs
                - cu
                - cv
                - cy
                - da
                - de
                - de-AT
                - de-CH
                - dv
                - dz
                - ee
                - el
                - en
                - en-AU
                - en-CA
                - en-GB
                - en-IN
                - en-NZ
                - en-US
                - eo
                - es
                - es-419
                - es-CL
                - es-EC
                - es-MX
                - et
                - eu
                - fa
                - ff
                - fi
                - fj
                - fo
                - fr
                - fr-CA
                - fy
                - ga
                - gd
                - gl
                - gn
                - gu
                - gv
                - ha
                - he
                - hi
                - ho
                - hr
                - ht
                - hu
                - hy
                - hz
                - ia
                - id
                - ie
                - ig
                - ii
                - ik
                - io
                - is
                - it
                - iu
                - ja
                - jv
                - ka
                - kg
                - ki
                - kj
                - kk
                - kl
                - km
                - kn
                - ko
                - kr
                - ks
                - ku
                - kv
                - kw
                - ky
                - la
                - lb
                - lg
                - li
                - ln
                - lo
                - lt
                - lu
                - lv
                - mg
                - mh
                - mi
                - mk
                - ml
                - mn
                - mr
                - ms
                - mt
                - my
                - na
                - nb
                - nd
                - ne
                - ng
                - nl
                - nn
                - 'no'
                - nr
                - nv
                - ny
                - oc
                - oj
                - om
                - or
                - os
                - pa
                - pi
                - pl
                - ps
                - pt
                - pt-BR
                - pt-PT
                - qu
                - rm
                - rn
                - ro
                - ru
                - rw
                - sa
                - sc
                - sd
                - se
                - sg
                - si
                - sk
                - sl
                - sl-SI
                - sm
                - sn
                - so
                - sq
                - sr
                - ss
                - st
                - su
                - sv
                - sw
                - ta
                - te
                - tg
                - th
                - ti
                - tk
                - tl
                - tn
                - to
                - tr
                - ts
                - tt
                - tw
                - ty
                - ug
                - uk
                - ur
                - uz
                - ve
                - vi
                - vo
                - wa
                - wo
                - xh
                - yi
                - yo
                - za
                - zh-CN
                - zh-HK
                - zh-TW
                - zu
                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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /store -d '{"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
                name: Renamed Store
                seo_title:
                meta_description: Sample store description.
                metadata: {}
                code: spree_1
                default_currency: USD
                default_locale: en
                default_country_code: US
                mail_from_address: no-reply@example.com
                customer_support_email: support@example.com
                new_order_notifications_email: store-owner@example.com
                created_at: '2026-11-11T12:45:25.412Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                order_routing_strategy: rules
                payout_provider:
                admin_locale:
                timezone: UTC
                storefront_url:
                weight_unit: lb
                unit_system: imperial
                storefront_access: public
                guest_checkout: true
                always_include_confirm_step: false
                company_field_enabled: false
                address_requires_company: false
                address_requires_phone: false
                capture_method: checkout
                track_inventory_levels: true
                stock_reservations_enabled: true
                low_stock_threshold: 5
                tax_using_ship_address: true
                track_price_history: true
                show_products_without_price: false
                disable_sku_validation: false
                pricing_provider: internal
                inventory_provider: internal
                pricing_provider_failure_policy: strict
                inventory_provider_failure_policy: fallback
                default_payouts_schedule_interval: monthly
                auto_approve_sellers: false
                auto_approve_seller_products: false
                seller_digital_assets_enabled: false
                seller_digital_asset_content_types:
                - application/pdf
                - application/epub+zip
                - application/zip
                - application/x-7z-compressed
                - application/gzip
                - application/json
                - text/plain
                - text/csv
                - audio/mpeg
                - audio/mp4
                - audio/aac
                - audio/flac
                - audio/ogg
                - audio/wav
                - audio/x-wav
                - audio/midi
                - video/mp4
                - video/webm
                - video/quicktime
                - image/jpeg
                - image/png
                - image/gif
                - image/webp
                - image/tiff
                review_seller_digital_asset_changes: true
                send_seller_transactional_emails: true
                document_number_format: sequential
                order_number_prefix: R
                order_number_suffix: ''
                order_number_sequence_start: 1001
                limit_digital_download_count: true
                digital_asset_authorized_clicks: 5
                limit_digital_download_days: true
                digital_asset_authorized_days: 7
                send_consumer_transactional_emails: true
                email_accent_color:
                email_background_color:
                email_card_color:
                email_text_color:
                email_heading_color:
                email_font:
                order_number_sequence_started: false
                default_minimum_payout_amount: '0.00'
                default_commission_tax_rate: '0'
                url: http://www.example.com:3000
                api_url: http://www.example.com:3000
                setup_tasks:
                - name: setup_address
                  done: false
                - name: setup_payment_method
                  done: false
                - name: add_products
                  done: false
                - name: set_customer_support_email
                  done: true
                - name: setup_taxes_collection
                  done: false
                - name: setup_storefront
                  done: false
                supported_currencies:
                - USD
                - EUR
                - GBP
                supported_locales:
                - en
                available_locales:
                - aa
                - ab
                - ae
                - af
                - ak
                - am
                - an
                - ar
                - as
                - av
                - ay
                - az
                - ba
                - be
                - bg
                - bh
                - bi
                - bm
                - bn
                - bo
                - br
                - bs
                - ca
                - ce
                - ch
                - co
                - cr
                - cs
                - cu
                - cv
                - cy
                - da
                - de
                - de-AT
                - de-CH
                - dv
                - dz
                - ee
                - el
                - en
                - en-AU
                - en-CA
                - en-GB
                - en-IN
                - en-NZ
                - en-US
                - eo
                - es
                - es-419
                - es-CL
                - es-EC
                - es-MX
                - et
                - eu
                - fa
                - ff
                - fi
                - fj
                - fo
                - fr
                - fr-CA
                - fy
                - ga
                - gd
                - gl
                - gn
                - gu
                - gv
                - ha
                - he
                - hi
                - ho
                - hr
                - ht
                - hu
                - hy
                - hz
                - ia
                - id
                - ie
                - ig
                - ii
                - ik
                - io
                - is
                - it
                - iu
                - ja
                - jv
                - ka
                - kg
                - ki
                - kj
                - kk
                - kl
                - km
                - kn
                - ko
                - kr
                - ks
                - ku
                - kv
                - kw
                - ky
                - la
                - lb
                - lg
                - li
                - ln
                - lo
                - lt
                - lu
                - lv
                - mg
                - mh
                - mi
                - mk
                - ml
                - mn
                - mr
                - ms
                - mt
                - my
                - na
                - nb
                - nd
                - ne
                - ng
                - nl
                - nn
                - 'no'
                - nr
                - nv
                - ny
                - oc
                - oj
                - om
                - or
                - os
                - pa
                - pi
                - pl
                - ps
                - pt
                - pt-BR
                - pt-PT
                - qu
                - rm
                - rn
                - ro
                - ru
                - rw
                - sa
                - sc
                - sd
                - se
                - sg
                - si
                - sk
                - sl
                - sl-SI
                - sm
                - sn
                - so
                - sq
                - sr
                - ss
                - st
                - su
                - sv
                - sw
                - ta
                - te
                - tg
                - th
                - ti
                - tk
                - tl
                - tn
                - to
                - tr
                - ts
                - tt
                - tw
                - ty
                - ug
                - uk
                - ur
                - uz
                - ve
                - vi
                - vo
                - wa
                - wo
                - xh
                - yi
                - yo
                - za
                - zh-CN
                - zh-HK
                - zh-TW
                - zu
                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:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/StoreUpdateParams"
        required: true
  "/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: 'customer',
            q: 'vip',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /tags -d '{"taggable_type":"customer","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: 'Shorthand of the tagged resource: `product`, `order` or `customer`'
        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 product, order, customer
  "/api/v3/admin/tax_categories":
    get:
      summary: List tax categories
      tags:
      - Settings
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the tax categories products and delivery methods can be assigned to, which tax rates then apply to.

        **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: taxCategories } = await client.taxCategories.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /tax_categories
      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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `is_default` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `tax_code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: TaxCategory
        sortable:
        - created_at
        - id
        - is_default
        - name
        - tax_code
        - updated_at
      responses:
        '200':
          description: tax categories found
          content:
            application/json:
              example:
                data:
                - id: taxcat_UkLWZg9DAJ
                  name: Clothing
                  tax_code:
                  description: Accusamus architecto mollitia possimus eos tempore
                    laudantium.
                  is_default: false
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                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/TaxCategory"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Create a tax category
      tags:
      - Settings
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Creates a tax category. `tax_code` is the code a tax provider uses to classify the goods in it.

        **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 taxCategory = await client.taxCategories.create({
            name: 'Food',
            tax_code: 'PF050000',
            description: 'Groceries and prepared food',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /tax_categories -d '{"name":"Food","tax_code":"PF050000","description":"Groceries
          and prepared food"}'
      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: tax category created
          content:
            application/json:
              example:
                id: taxcat_gbHJdmfrXB
                name: Food
                tax_code: PF050000
                description: Groceries and prepared food
                is_default: false
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/TaxCategory"
        '422':
          description: validation failed
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaxCategoryCreateParams"
        required: true
  "/api/v3/admin/tax_categories/{id}":
    parameters:
    - name: id
      in: path
      description: Tax category ID
      required: true
      schema:
        type: string
    patch:
      summary: Update a tax category
      tags:
      - Settings
      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',
          })

          // Making a category the default moves the flag off the previous one.
          const taxCategory = await client.taxCategories.update('taxcat_UkLWZg9DAJ', {
            name: 'Apparel',
            is_default: true,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /tax_categories/{id} -d '{"name":"Apparel","is_default":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
      responses:
        '200':
          description: tax category updated
          content:
            application/json:
              example:
                id: taxcat_UkLWZg9DAJ
                name: Apparel
                tax_code:
                description: Illo sapiente voluptatibus dignissimos autem.
                is_default: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/TaxCategory"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaxCategoryUpdateParams"
        required: true
  "/api/v3/admin/tax_rates":
    get:
      summary: List tax rates
      tags:
      - Settings
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the store's tax rates. Rates are the entire configuration of
        the built-in tax provider: each pairs a tax category with a jurisdiction
        (a country, optionally narrowed to one state) and a percentage. Whether
        the tax is included in the product price (VAT-style) or added on top
        (US-style) is the market's `tax_inclusive` setting.

        Markets using an external tax provider ignore these rows — that
        provider carries its own jurisdiction data.


        **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: taxRates } = await client.taxRates.list({ country_code_eq: 'DE' })
      - lang: bash
        label: Spree CLI
        source: spree api get /tax_rates -d '{"country_code_eq":"DE"}'
      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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: sort
        in: query
        required: false
        description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`).
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `amount` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `country_code` | One of the `CountryCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `state_code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `tax_category_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `amount`, `country_code`, `created_at`, `id`, `name`, `state_code`, `tax_category_id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: TaxRate
        sortable:
        - amount
        - country_code
        - created_at
        - id
        - name
        - rate
        - state_code
        - tax_category_id
        - updated_at
      responses:
        '200':
          description: tax rates found
          content:
            application/json:
              example:
                data:
                - id: tax_UkLWZg9DAJ
                  name: TaxRate - 124492
                  show_rate_in_label: true
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  deleted_at:
                  rate: '0.19'
                  rate_percent: '19'
                  tax_category_id: taxcat_UkLWZg9DAJ
                  store_id: store_UkLWZg9DAJ
                  country_code: DE
                  state_code:
                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/TaxRate"
                  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 tax rate
      tags:
      - Settings
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Creates a tax rate for the current store. Give either `rate` as a
        decimal string (`"0.19"`) or `rate_percent` as a percentage string (`"19"`).

        Name the jurisdiction with `country_code` (and `state_code` for a
        state-level rate). Omitting the country makes the rate apply everywhere.


        **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',
          })

          // A rate names the jurisdiction it applies to; one naming no country taxes everywhere.
          const taxRate = await client.taxRates.create({
            name: 'German VAT',
            rate_percent: '19',
            country_code: 'DE',
            tax_category_id: 'txc_UkLWZg9DAJ',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /tax_rates -d '{"name":"German VAT","rate_percent":"19","country_code":"DE","tax_category_id":"txc_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:
        '201':
          description: tax rate created
          content:
            application/json:
              example:
                id: tax_gbHJdmfrXB
                name: VAT
                show_rate_in_label: true
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                rate: '0.19'
                rate_percent: '19'
                tax_category_id: taxcat_UkLWZg9DAJ
                store_id: store_UkLWZg9DAJ
                country_code: DE
                state_code:
              schema:
                "$ref": "#/components/schemas/TaxRate"
        '422':
          description: validation failed
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Tax category must exist and Name can't be blank
                  details:
                    tax_category:
                    - code: blank
                      message: must exist
                      specific: true
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaxRateCreateParams"
        required: true
  "/api/v3/admin/tax_rates/{id}":
    parameters:
    - name: id
      in: path
      description: Tax rate ID
      required: true
      schema:
        type: string
    get:
      summary: Get a tax rate
      tags:
      - Settings
      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 taxRate = await client.taxRates.get('tax_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /tax_rates/{id}
      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: tax rate found
          content:
            application/json:
              example:
                id: tax_UkLWZg9DAJ
                name: TaxRate - 312890
                show_rate_in_label: true
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                rate: '0.19'
                rate_percent: '19'
                tax_category_id: taxcat_UkLWZg9DAJ
                store_id: store_UkLWZg9DAJ
                country_code: DE
                state_code:
              schema:
                "$ref": "#/components/schemas/TaxRate"
    patch:
      summary: Update a tax rate
      tags:
      - Settings
      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 taxRate = await client.taxRates.update('tax_UkLWZg9DAJ', { rate_percent: '7' })
      - lang: bash
        label: Spree CLI
        source: spree api patch /tax_rates/{id} -d '{"rate_percent":"7"}'
      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: tax rate updated
          content:
            application/json:
              example:
                id: tax_UkLWZg9DAJ
                name: TaxRate - 470830
                show_rate_in_label: true
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                rate: '0.07'
                rate_percent: '7'
                tax_category_id: taxcat_UkLWZg9DAJ
                store_id: store_UkLWZg9DAJ
                country_code: DE
                state_code:
              schema:
                "$ref": "#/components/schemas/TaxRate"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaxRateUpdateParams"
        required: true
    delete:
      summary: Delete a tax rate
      tags:
      - Settings
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Soft-deletes the rate. Tax lines it already produced keep their own rate snapshot.

        **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.taxRates.delete('tax_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /tax_rates/{id}
      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: tax rate deleted
  "/api/v3/admin/translatable_resources":
    get:
      summary: List translatable resources
      tags:
      - Settings
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns every translatable resource type and its translatable fields (key + content type), so clients can render translation editors generically.

        **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 resources = await client.translatableResources.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /translatable_resources
      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: translatable resources found
          content:
            application/json:
              example:
                data:
                - resource_type: option_type
                  fields:
                  - key: label
                    type: string
                  readable: true
                - resource_type: option_value
                  fields:
                  - key: label
                    type: string
                  readable: false
                - resource_type: product
                  fields:
                  - key: name
                    type: string
                  - key: description
                    type: html
                  - key: slug
                    type: string
                  - key: meta_description
                    type: string
                  - key: meta_title
                    type: string
                  readable: true
                - resource_type: product_type
                  fields:
                  - key: name
                    type: string
                  readable: false
                - resource_type: collection
                  fields:
                  - key: name
                    type: string
                  - key: description
                    type: html
                  - key: permalink
                    type: string
                  readable: true
                - resource_type: category
                  fields:
                  - key: name
                    type: string
                  - key: pretty_name
                    type: string
                  - key: description
                    type: html
                  - key: permalink
                    type: string
                  readable: true
                - resource_type: store
                  fields:
                  - key: name
                    type: string
                  - key: meta_description
                    type: string
                  - key: meta_keywords
                    type: string
                  - key: seo_title
                    type: string
                  - key: customer_support_email
                    type: string
                  - key: address
                    type: string
                  - key: contact_phone
                    type: string
                  readable: true
                - resource_type: policy
                  fields:
                  - key: name
                    type: string
                  - key: body
                    type: html
                  readable: true
                - resource_type: seller
                  fields:
                  - key: name
                    type: string
                  - key: about
                    type: html
                  readable: false
  "/api/v3/admin/translations/batch":
    post:
      summary: Batch upsert translations
      tags:
      - Settings
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Atomically upserts translations across many records of (possibly) different translatable resource types in one request — e.g. an option type and all its option values in one save. A flat list of independent registry writes; all entries succeed or none do.

        **Required scope:** `write_<resource>` for every resource type in the batch (for API-key authentication) (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',
          })

          // All entries are saved together, or none are.
          const translations = await client.translations.batch([
            {
              resource_type: 'option_type',
              resource_id: 'opt_UkLWZg9DAJ',
              values: { de: { label: 'Größe' } },
            },
            {
              resource_type: 'option_value',
              resource_id: 'optval_UkLWZg9DAJ',
              values: { de: { label: 'Klein' } },
            },
          ])
      - lang: bash
        label: Spree CLI
        source: spree api post /translations/batch -d '{ ... }'
      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: translations upserted
          content:
            application/json:
              example:
                data:
                - resource_id: opt_UkLWZg9DAJ
                  resource_type: option_type
                  translations:
                    de:
                      label: Größe
                      translated_field_count: 1
                    fr:
                      label:
                      translated_field_count: 0
                  default_locale: en
                  supported_locales:
                  - de
                  - en
                  - fr
                - resource_id: optval_UkLWZg9DAJ
                  resource_type: option_value
                  translations:
                    de:
                      label: Klein
                      translated_field_count: 1
                    fr:
                      label:
                      translated_field_count: 0
                  default_locale: en
                  supported_locales:
                  - de
                  - en
                  - fr
        '422':
          description: unsupported locale rolls back the whole batch
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: 'Unsupported locale(s): es'
                  details:
                    translations:
                      '0':
                      - 'Unsupported locale(s): es'
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TranslationBatchParams"
        required: true
  "/api/v3/admin/updates":
    get:
      summary: Check for a newer Spree release
      tags:
      - Settings
      security:
      - bearer_auth: []
      description: |
        Whether a newer Spree release exists. The server asks spreecloud.io
        when it has no cached answer, for at most two seconds. A successful
        answer is kept for a day; a failed check is retried after an hour, so
        the call that retries it waits on it again. `checked_at` is null when
        the update check is turned off. Available to signed-in admins who can
        manage the store; a secret API key gets a 404.
      x-codeSamples:
      - lang: javascript
        label: Spree Admin SDK
        source: |-
          import { createAdminClient } from '@spree/admin-sdk'

          const client = createAdminClient({
            baseUrl: 'https://your-store.com',
            jwtToken: 'eyJhbGciOi...',
          })

          // Needs a client created with `jwtToken`: a secret key is refused.
          const status = await client.updates.get()
          if (status.update_available) {
            console.log(`Spree ${status.latest_version} is available: ${status.latest_release_url}`)
          }
      parameters:
      - name: Authorization
        in: header
        required: true
        description: Bearer token for admin authentication
        schema:
          type: string
      responses:
        '200':
          description: update status
          content:
            application/json:
              example:
                current_version: 6.0.3
                enabled: true
                checked_at: '2026-10-03T04:00:00.000Z'
                update_available: true
                latest_version: 6.0.1
                latest_release_url: https://github.com/spree/spree/releases/tag/v6.0.1
                latest_release_published_at: '2026-10-02T10:51:38.000Z'
              schema:
                "$ref": "#/components/schemas/UpdateStatus"
        '401':
          description: unauthorized
          content:
            application/json:
              example:
                error:
                  code: authentication_required
                  message: Authentication required
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/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_staff` (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()
      - lang: bash
        label: Spree CLI
        source: spree api get /admin_users
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[email_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `email` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `first_name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `last_name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[spree_roles_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `spree_roles_` | `created_at`, `id`, `name`, `updated_at` |

          </Accordion>

          **Sort by:** `created_at`, `email`, `first_name`, `id`, `last_name`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: AdminUser
        sortable:
        - created_at
        - email
        - first_name
        - id
        - last_name
        - updated_at
      responses:
        '200':
          description: staff found
          content:
            application/json:
              example:
                data:
                - id: adm_UkLWZg9DAJ
                  email: jeffery_lindgren@littelcassin.ca
                  first_name: Carole
                  last_name: Kling
                  full_name: Carole Kling
                  selected_locale:
                  status: active
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  last_active_at:
                  avatar_url:
                  roles:
                  - id: role_UkLWZg9DAJ
                    name: admin
                  stores:
                  - id: store_UkLWZg9DAJ
                    name: Spree Test Store
                    code: spree_1
                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_staff` (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')
      - lang: bash
        label: Spree CLI
        source: spree api get /admin_users/{id}
      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 fields to expand: inviter, sessions.'
        schema:
          type: string
      responses:
        '200':
          description: staff member found with sessions and inviter
          content:
            application/json:
              example:
                id: adm_UkLWZg9DAJ
                email: karie.marquardt@keebler.ca
                first_name: Lester
                last_name: Bartoletti
                full_name: Lester Bartoletti
                selected_locale:
                status: active
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                last_active_at: '2026-01-15T12:00:00Z'
                avatar_url:
                roles:
                - id: role_UkLWZg9DAJ
                  name: admin
                stores:
                - id: store_UkLWZg9DAJ
                  name: Spree Test Store
                  code: spree_1
                sessions:
                - id: rt_UkLWZg9DAJ
                  ip_address: 203.0.113.7
                  user_agent: Mozilla/5.0 Firefox/131.0
                  last_active_at: '2026-01-15T12:00:00.000Z'
                inviter:
                  id: adm_gbHJdmfrXB
                  type: admin_user
                  label: Ada Inviter
    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_staff` (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'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /admin_users/{id} -d '{"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: adm_UkLWZg9DAJ
                email: chan.schmidt@okon.biz
                first_name: Renamed
                last_name: King
                full_name: Renamed King
                selected_locale:
                status: active
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                last_active_at:
                avatar_url:
                roles:
                - id: role_UkLWZg9DAJ
                  name: admin
                stores:
                - id: store_UkLWZg9DAJ
                  name: Spree Test Store
                  code: spree_1
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/AdminUserUpdateParams"
        required: true
    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. Removing a role needs the same rights as granting it, and the store always keeps at least one admin.

        **Required scope:** `write_staff` (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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /admin_users/{id}
      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_staff` (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()
      - lang: bash
        label: Spree CLI
        source: spree api get /invitations
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Invitation
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: invitations found
          content:
            application/json:
              example:
                data:
                - id: inv_UkLWZg9DAJ
                  email: tillie_rolfson@quigley.info
                  status: pending
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  expires_at: '2026-01-29T12:00:00.000Z'
                  role_id: role_UkLWZg9DAJ
                  role_name: admin
                  inviter_email: teisha_prohaska@mcdermott.us
                  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_staff` (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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /invitations -d '{"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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                expires_at: '2026-01-29T12:00:00.000Z'
                role_id: role_UkLWZg9DAJ
                role_name: admin
                inviter_email: xavier_zemlak@jones.co.uk
                invitee_exists: false
                store:
                  id: store_UkLWZg9DAJ
                  name: Spree Test Store
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/InvitationCreateParams"
        required: true
  "/api/v3/admin/invitations/{id}":
    delete:
      summary: Revoke an invitation
      tags:
      - Staff
      security:
      - api_key: []
        bearer_auth: []
      description: "**Required scope:** `write_staff` (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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /invitations/{id}
      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/{invitation_id}/acceptance_link":
    get:
      summary: Get an invitation acceptance link
      tags:
      - Staff
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the link the invitee opens to accept a pending invitation. The link carries the invitation token, so it needs write access to staff and the right to grant the invitation's role; invitation listings never include it.

        **Required scope:** `write_staff` (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 { acceptance_url } = await client.invitations.acceptanceLink('inv_xxx')
      - lang: bash
        label: Spree CLI
        source: spree api get /invitations/{invitation_id}/acceptance_link
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: invitation_id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: acceptance link found
          content:
            application/json:
              example:
                id: inv_UkLWZg9DAJ
                acceptance_url: http://www.example.com:3000/accept-invitation/inv_UkLWZg9DAJ?token=jDy3giwKk1iUW1wTMg5LRLEG
              schema:
                "$ref": "#/components/schemas/InvitationAcceptanceLink"
  "/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_staff` (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')
      - lang: bash
        label: Spree CLI
        source: spree api patch /invitations/{id}/resend -d '{ ... }'
      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: kecia@hirthedamore.biz
                status: pending
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                expires_at: '2026-01-29T12:00:00.000Z'
                role_id: role_UkLWZg9DAJ
                role_name: admin
                inviter_email: fumiko@jacobsonkirlin.co.uk
                invitee_exists: false
                store:
                  id: store_UkLWZg9DAJ
                  name: Spree Test Store
  "/api/v3/admin/permissions":
    get:
      summary: List the permission catalog
      tags:
      - Staff
      security:
      - api_key: []
        bearer_auth: []
      description: Returns the permission catalog — the grant vocabulary shared by
        staff role permissions and secret API key scopes. Entries are grouped for
        permission pickers; labels and descriptions are localized. Readable by any
        authenticated admin credential.
      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: permissions } = await client.permissions.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /permissions
      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: catalog returned
          content:
            application/json:
              example:
                data:
                - key: read_dashboard
                  resource: dashboard
                  kind: read
                  group: analytics
                  group_label: Analytics
                  label: Analytics dashboard
                  description: Sales and performance analytics
                - key: read_reports
                  resource: reports
                  kind: read
                  group: analytics
                  group_label: Analytics
                  label: Reports
                  description: ''
                - key: write_reports
                  resource: reports
                  kind: write
                  group: analytics
                  group_label: Analytics
                  label: Reports
                  description: ''
                - key: read_orders
                  resource: orders
                  kind: read
                  group: orders
                  group_label: Orders
                  label: Orders
                  description: Orders, line items, returns, exchanges and claims
                - key: write_orders
                  resource: orders
                  kind: write
                  group: orders
                  group_label: Orders
                  label: Orders
                  description: Orders, line items, returns, exchanges and claims
                - key: read_payments
                  resource: payments
                  kind: read
                  group: orders
                  group_label: Orders
                  label: Payments
                  description: Order payments and payment capture
                - key: write_payments
                  resource: payments
                  kind: write
                  group: orders
                  group_label: Orders
                  label: Payments
                  description: Order payments and payment capture
                - key: read_fulfillments
                  resource: fulfillments
                  kind: read
                  group: orders
                  group_label: Orders
                  label: Fulfillments
                  description: Pack, ship and track order fulfillments
                - key: write_fulfillments
                  resource: fulfillments
                  kind: write
                  group: orders
                  group_label: Orders
                  label: Fulfillments
                  description: Pack, ship and track order fulfillments
                - key: read_refunds
                  resource: refunds
                  kind: read
                  group: orders
                  group_label: Orders
                  label: Refunds
                  description: Issue and view refunds
                - key: write_refunds
                  resource: refunds
                  kind: write
                  group: orders
                  group_label: Orders
                  label: Refunds
                  description: Issue and view refunds
                - key: read_products
                  resource: products
                  kind: read
                  group: catalog
                  group_label: Catalog
                  label: Products
                  description: Products, variants, options, prices and media
                - key: write_products
                  resource: products
                  kind: write
                  group: catalog
                  group_label: Catalog
                  label: Products
                  description: Products, variants, options, prices and media
                - key: read_product_types
                  resource: product_types
                  kind: read
                  group: catalog
                  group_label: Catalog
                  label: Product types
                  description: ''
                - key: write_product_types
                  resource: product_types
                  kind: write
                  group: catalog
                  group_label: Catalog
                  label: Product types
                  description: ''
                - key: read_publishing
                  resource: publishing
                  kind: read
                  group: catalog
                  group_label: Catalog
                  label: Publishing
                  description: ''
                - key: write_publishing
                  resource: publishing
                  kind: write
                  group: catalog
                  group_label: Catalog
                  label: Publishing
                  description: ''
                - key: read_media
                  resource: media
                  kind: read
                  group: catalog
                  group_label: Catalog
                  label: Media
                  description: ''
                - key: write_media
                  resource: media
                  kind: write
                  group: catalog
                  group_label: Catalog
                  label: Media
                  description: ''
                - key: read_categories
                  resource: categories
                  kind: read
                  group: catalog
                  group_label: Catalog
                  label: Categories
                  description: Category tree and taxonomies
                - key: write_categories
                  resource: categories
                  kind: write
                  group: catalog
                  group_label: Catalog
                  label: Categories
                  description: Category tree and taxonomies
                - key: read_collections
                  resource: collections
                  kind: read
                  group: catalog
                  group_label: Catalog
                  label: Collections
                  description: Manual and rule-based product collections
                - key: write_collections
                  resource: collections
                  kind: write
                  group: catalog
                  group_label: Catalog
                  label: Collections
                  description: Manual and rule-based product collections
                - key: read_stock
                  resource: stock
                  kind: read
                  group: catalog
                  group_label: Catalog
                  label: Inventory
                  description: Stock levels, locations, movements and transfers
                - key: write_stock
                  resource: stock
                  kind: write
                  group: catalog
                  group_label: Catalog
                  label: Inventory
                  description: Stock levels, locations, movements and transfers
                - key: read_purchasing
                  resource: purchasing
                  kind: read
                  group: catalog
                  group_label: Catalog
                  label: Purchasing
                  description: Suppliers and purchase orders
                - key: write_purchasing
                  resource: purchasing
                  kind: write
                  group: catalog
                  group_label: Catalog
                  label: Purchasing
                  description: Suppliers and purchase orders
                - key: read_customers
                  resource: customers
                  kind: read
                  group: customers
                  group_label: Customers
                  label: Customers
                  description: Customer accounts, addresses, cards and groups
                - key: write_customers
                  resource: customers
                  kind: write
                  group: customers
                  group_label: Customers
                  label: Customers
                  description: Customer accounts, addresses, cards and groups
                - key: read_sellers
                  resource: sellers
                  kind: read
                  group: sellers
                  group_label: Sellers
                  label: Sellers
                  description: ''
                - key: write_sellers
                  resource: sellers
                  kind: write
                  group: sellers
                  group_label: Sellers
                  label: Sellers
                  description: ''
                - key: read_commissions
                  resource: commissions
                  kind: read
                  group: sellers
                  group_label: Sellers
                  label: Commissions
                  description: ''
                - key: write_commissions
                  resource: commissions
                  kind: write
                  group: sellers
                  group_label: Sellers
                  label: Commissions
                  description: ''
                - key: read_payouts
                  resource: payouts
                  kind: read
                  group: sellers
                  group_label: Sellers
                  label: Payouts
                  description: ''
                - key: write_payouts
                  resource: payouts
                  kind: write
                  group: sellers
                  group_label: Sellers
                  label: Payouts
                  description: ''
                - key: read_gift_cards
                  resource: gift_cards
                  kind: read
                  group: loyalty
                  group_label: Loyalty
                  label: Gift cards
                  description: Gift cards and gift card batches
                - key: write_gift_cards
                  resource: gift_cards
                  kind: write
                  group: loyalty
                  group_label: Loyalty
                  label: Gift cards
                  description: Gift cards and gift card batches
                - key: read_store_credits
                  resource: store_credits
                  kind: read
                  group: loyalty
                  group_label: Loyalty
                  label: Store credits
                  description: Customer store credit balances
                - key: write_store_credits
                  resource: store_credits
                  kind: write
                  group: loyalty
                  group_label: Loyalty
                  label: Store credits
                  description: Customer store credit balances
                - key: read_promotions
                  resource: promotions
                  kind: read
                  group: marketing
                  group_label: Marketing
                  label: Promotions
                  description: Promotions, rules and coupon codes
                - key: write_promotions
                  resource: promotions
                  kind: write
                  group: marketing
                  group_label: Marketing
                  label: Promotions
                  description: Promotions, rules and coupon codes
                - key: read_settings
                  resource: settings
                  kind: read
                  group: settings
                  group_label: Settings
                  label: Store settings
                  description: Store, payment, delivery, tax and channel configuration
                - key: write_settings
                  resource: settings
                  kind: write
                  group: settings
                  group_label: Settings
                  label: Store settings
                  description: Store, payment, delivery, tax and channel configuration
                - key: read_delivery_methods
                  resource: delivery_methods
                  kind: read
                  group: settings
                  group_label: Settings
                  label: Delivery methods
                  description: ''
                - key: write_delivery_methods
                  resource: delivery_methods
                  kind: write
                  group: settings
                  group_label: Settings
                  label: Delivery methods
                  description: ''
                - key: read_package_types
                  resource: package_types
                  kind: read
                  group: settings
                  group_label: Settings
                  label: Package types
                  description: ''
                - key: write_package_types
                  resource: package_types
                  kind: write
                  group: settings
                  group_label: Settings
                  label: Package types
                  description: ''
                - key: read_webhooks
                  resource: webhooks
                  kind: read
                  group: settings
                  group_label: Settings
                  label: Webhooks
                  description: Webhook endpoints and deliveries
                - key: write_webhooks
                  resource: webhooks
                  kind: write
                  group: settings
                  group_label: Settings
                  label: Webhooks
                  description: Webhook endpoints and deliveries
                - key: read_email_templates
                  resource: email_templates
                  kind: read
                  group: settings
                  group_label: Settings
                  label: Email templates
                  description: Customer email templates and the email layout
                - key: write_email_templates
                  resource: email_templates
                  kind: write
                  group: settings
                  group_label: Settings
                  label: Email templates
                  description: Customer email templates and the email layout
                - key: read_integrations
                  resource: integrations
                  kind: read
                  group: settings
                  group_label: Settings
                  label: Integrations
                  description: ''
                - key: write_integrations
                  resource: integrations
                  kind: write
                  group: settings
                  group_label: Settings
                  label: Integrations
                  description: ''
                - key: read_maintenance_tasks
                  resource: maintenance_tasks
                  kind: read
                  group: access
                  group_label: Access
                  label: Maintenance tasks
                  description: ''
                - key: write_maintenance_tasks
                  resource: maintenance_tasks
                  kind: write
                  group: access
                  group_label: Access
                  label: Maintenance tasks
                  description: ''
                - key: read_api_keys
                  resource: api_keys
                  kind: read
                  group: access
                  group_label: Access
                  label: API keys
                  description: Create and revoke API credentials
                - key: write_api_keys
                  resource: api_keys
                  kind: write
                  group: access
                  group_label: Access
                  label: API keys
                  description: Create and revoke API credentials
                - key: read_oauth_applications
                  resource: oauth_applications
                  kind: read
                  group: access
                  group_label: Access
                  label: Oauth applications
                  description: ''
                - key: write_oauth_applications
                  resource: oauth_applications
                  kind: write
                  group: access
                  group_label: Access
                  label: Oauth applications
                  description: ''
                - key: read_staff
                  resource: staff
                  kind: read
                  group: access
                  group_label: Access
                  label: Staff & roles
                  description: Team members, invitations, roles and their permissions
                - key: write_staff
                  resource: staff
                  kind: write
                  group: access
                  group_label: Access
                  label: Staff & roles
                  description: Team members, invitations, roles and their permissions
                meta:
                  count: 61
  "/api/v3/admin/roles":
    get:
      summary: List roles
      tags:
      - Staff
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns staff roles with their catalog permissions. Roles are global, not per-store; `mutable: false` marks the protected admin role and host-locked rows.

        **Required scope:** `read_staff` (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()
      - lang: bash
        label: Spree CLI
        source: spree api get /roles
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `name`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Role
        sortable:
        - created_at
        - id
        - name
        - updated_at
      responses:
        '200':
          description: roles found
          content:
            application/json:
              example:
                data:
                - id: role_UkLWZg9DAJ
                  name: admin
                  description:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  permissions:
                  - read_dashboard
                  - read_reports
                  - write_reports
                  - read_orders
                  - write_orders
                  - read_payments
                  - write_payments
                  - read_fulfillments
                  - write_fulfillments
                  - read_refunds
                  - write_refunds
                  - read_products
                  - write_products
                  - read_product_types
                  - write_product_types
                  - read_publishing
                  - write_publishing
                  - read_media
                  - write_media
                  - read_categories
                  - write_categories
                  - read_collections
                  - write_collections
                  - read_stock
                  - write_stock
                  - read_purchasing
                  - write_purchasing
                  - read_customers
                  - write_customers
                  - read_sellers
                  - write_sellers
                  - read_commissions
                  - write_commissions
                  - read_payouts
                  - write_payouts
                  - read_gift_cards
                  - write_gift_cards
                  - read_store_credits
                  - write_store_credits
                  - read_promotions
                  - write_promotions
                  - read_settings
                  - write_settings
                  - read_delivery_methods
                  - write_delivery_methods
                  - read_package_types
                  - write_package_types
                  - read_webhooks
                  - write_webhooks
                  - read_email_templates
                  - write_email_templates
                  - read_integrations
                  - write_integrations
                  - read_maintenance_tasks
                  - write_maintenance_tasks
                  - read_api_keys
                  - write_api_keys
                  - read_oauth_applications
                  - write_oauth_applications
                  - read_staff
                  - write_staff
                  mutable: false
                  users_count: 1
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Create a role
      tags:
      - Staff
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Creates a staff role. `permissions` holds catalog keys (see GET /admin/permissions); a caller may only grant keys they effectively hold.

        **Required scope:** `write_staff` (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 role = await client.roles.create({
            name: 'order_manager',
            description: 'Handles daily orders',
            permissions: ['write_orders', 'read_customers'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /roles -d '{"name":"order_manager","description":"Handles
          daily orders","permissions":["write_orders","read_customers"]}'
      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: role created
          content:
            application/json:
              example:
                id: role_gbHJdmfrXB
                name: order_manager
                description: Handles daily orders
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                permissions:
                - write_orders
                - read_customers
                mutable: true
                users_count: 0
        '422':
          description: invalid request
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: 'Permissions contains unknown permissions: write_bogus
                    and Permissions cannot be granted to a store role: write_bogus'
                  details:
                    permissions:
                    - code: role_permissions_unknown
                      message: 'contains unknown permissions: write_bogus'
                      specific: false
                    - code: role_permissions_not_grantable_for_audience
                      message: 'cannot be granted to a store role: write_bogus'
                      specific: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/RoleCreateParams"
        required: true
  "/api/v3/admin/roles/{id}":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
    patch:
      summary: Update a role
      tags:
      - Staff
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Updates a role name, description or permissions. The admin role and host-locked roles (`mutable: false`) reject changes.

        **Required scope:** `write_staff` (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 role = await client.roles.update('role_abc123', {
            permissions: ['write_orders', 'write_payments', 'read_customers'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /roles/{id} -d '{"permissions":["write_orders","write_payments","read_customers"]}'
      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: role updated
          content:
            application/json:
              example:
                id: role_gbHJdmfrXB
                name: support
                description:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                permissions:
                - read_orders
                - read_customers
                mutable: true
                users_count: 0
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/RoleUpdateParams"
        required: true
    delete:
      summary: Delete a role
      tags:
      - Staff
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Deletes a role. Fails with 422 while the role is protected or still referenced by staff members or pending invitations.

        **Required scope:** `write_staff` (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.roles.delete('role_abc123')
      - lang: bash
        label: Spree CLI
        source: spree api delete /roles/{id}
      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: role deleted
        '422':
          description: role cannot be deleted
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Roles cannot be deleted
  "/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()
      - lang: bash
        label: Spree CLI
        source: spree api get /stock_locations
      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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - 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
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `active` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `country_code` | One of the `CountryCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `default` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `kind` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `pickup_enabled` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `returns_enabled` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `seller_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `state_code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[seller_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |

          </Accordion>

          **Sort by:** `active`, `country_code`, `created_at`, `default`, `id`, `kind`, `name`, `pickup_enabled`, `returns_enabled`, `seller_id`, `state_code`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: StockLocation
        sortable:
        - active
        - country_code
        - created_at
        - default
        - id
        - kind
        - name
        - pickup_enabled
        - returns_enabled
        - seller_id
        - state_code
        - updated_at
      responses:
        '200':
          description: stock locations found
          content:
            application/json:
              example:
                data:
                - id: sloc_UkLWZg9DAJ
                  name: Brooklyn warehouse
                  address1: 1600 Pennsylvania Ave NW
                  city: Washington
                  zipcode: '20500'
                  country_code: US
                  country_name: United States
                  state_code: AL
                  state_text: AL
                  pickup_ready_in_minutes:
                  pickup_instructions:
                  external_references: {}
                  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
                  returns_enabled: true
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  seller_id:
                  seller_name:
                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_code: 'US',
            state_code: 'NY',
            city: 'Brooklyn',
            zipcode: '11201',
            pickup_enabled: true,
            pickup_stock_policy: 'local',
            pickup_ready_in_minutes: 60,
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /stock_locations -d '{"name":"Brooklyn warehouse","kind":"warehouse","country_code":"US","state_code":"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
                name: Manhattan store
                address1:
                city:
                zipcode:
                country_code:
                country_name:
                state_code:
                state_text:
                pickup_ready_in_minutes: 30
                pickup_instructions:
                external_references: {}
                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
                returns_enabled: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                seller_id:
                seller_name:
              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:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/StockLocationCreateParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /stock_locations/{id}
      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
                name: Brooklyn warehouse
                address1: 1600 Pennsylvania Ave NW
                city: Washington
                zipcode: '20500'
                country_code: US
                country_name: United States
                state_code: AL
                state_text: AL
                pickup_ready_in_minutes:
                pickup_instructions:
                external_references: {}
                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
                returns_enabled: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                seller_id:
                seller_name:
              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.',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /stock_locations/{id} -d '{"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
                name: Renamed warehouse
                address1: 1600 Pennsylvania Ave NW
                city: Washington
                zipcode: '20500'
                country_code: US
                country_name: United States
                state_code: AL
                state_text: AL
                pickup_ready_in_minutes: 45
                pickup_instructions:
                external_references: {}
                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
                returns_enabled: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                seller_id:
                seller_name:
              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:
                    - value: invalid
                      code: inclusion
                      message: is not included in the list
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/StockLocationUpdateParams"
        required: 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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /stock_locations/{id}
      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/store_credits/{store_credit_id}/custom_fields":
    get:
      summary: List store credit custom fields
      tags:
      - Store Credits
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the store credit's custom field values.

        **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: customFields } = await client.customFields('store_credit', 'credit_UkLWZg9DAJ').list()
      - lang: bash
        label: Spree CLI
        source: spree api get /store_credits/{store_credit_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: store_credit_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/store_credits":
    get:
      summary: List store credits
      tags:
      - Store Credits
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns every store credit in the current store, across all customers.
        Read-only: issuing, editing and deleting a credit stays nested under
        the customer that holds it.

        `meta.totals` carries the outstanding balance as one row per currency,
        summed over the same filter this request used — so filtering by a
        customer answers that customer's balance and no filter answers the
        store's liability.


        **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, meta } = await client.storeCredits.list({
            page: 1,
            limit: 25,
            outstanding: true,
            expand: ['customer', 'created_by'],
          })

          // What the store still owes, one row per currency, over the same filter.
          const outstanding = meta.totals
      - lang: bash
        label: Spree CLI
        source: spree api get /store_credits -d '{"page":1,"limit":25,"outstanding":true,"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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of memo (partial, case-insensitive).
      - name: q[from_gift_card]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `from_gift_card`.
      - name: q[outstanding]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `outstanding`.
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: expand
        in: query
        required: false
        description: Comma-separated associations to expand (customer, created_by).
        schema:
          type: string
      - name: sort
        in: query
        required: false
        description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`).
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[memo_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `amount` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_by_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `currency` | One of the `CurrencyCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `customer_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `memo` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[customer_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `customer_addresses_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customer_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customer_customer_groups_` | `created_at`, `id`, `name`, `updated_at` |
          | `customer_orders_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `customer_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `customer_spree_roles_` | `created_at`, `id`, `name`, `updated_at` |
          | `customer_tags_` | `created_at`, `id`, `name`, `updated_at` |

          </Accordion>

          **Sort by:** `amount`, `created_at`, `created_by_id`, `currency`, `customer_id`, `id`, `memo`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: StoreCredit
        sortable:
        - amount
        - created_at
        - created_by_id
        - currency
        - customer_id
        - id
        - memo
        - updated_at
      responses:
        '200':
          description: store credits found
          content:
            application/json:
              example:
                data:
                - id: credit_UkLWZg9DAJ
                  amount: '50.00'
                  amount_used: '0.00'
                  amount_remaining: '50.00'
                  currency: USD
                  memo:
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  amount_authorized: '0.00'
                  outstanding: true
                  customer_id: cust_UkLWZg9DAJ
                  created_by_id: adm_UkLWZg9DAJ
                  created_by_type: admin_user
                  originator_type:
                  originator_id:
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
                  totals:
                  - currency: USD
                    amount: '50.00'
                    amount_used: '0.00'
                    amount_authorized: '0.00'
                    amount_remaining: '50.00'
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/StoreCredit"
                  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_credits/{id}":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
    get:
      summary: Retrieve a store credit
      tags:
      - Store Credits
      security:
      - api_key: []
        bearer_auth: []
      description: "**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 storeCredit = await client.storeCredits.get('credit_abc123', {
            expand: ['customer', 'created_by'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /store_credits/{id} -d '{"expand":["customer","created_by"]}'
      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 (customer, created_by).
        schema:
          type: string
      responses:
        '200':
          description: store credit found
          content:
            application/json:
              example:
                id: credit_UkLWZg9DAJ
                amount: '50.00'
                amount_used: '0.00'
                amount_remaining: '50.00'
                currency: USD
                memo:
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                amount_authorized: '0.00'
                outstanding: true
                customer_id: cust_UkLWZg9DAJ
                created_by_id: adm_UkLWZg9DAJ
                created_by_type: admin_user
                originator_type:
                originator_id:
              schema:
                "$ref": "#/components/schemas/StoreCredit"
        '404':
          description: not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Store credit not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/store_credits/{store_credit_id}/events":
    parameters:
    - name: store_credit_id
      in: path
      required: true
      schema:
        type: string
    get:
      summary: List a store credit's ledger
      tags:
      - Store Credits
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Every movement of the credit's balance, newest first: allocated when
        issued, authorized when a checkout starts against it, captured when
        that order is paid, and voided or credited back if it is cancelled.


        **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: events } = await client.storeCredits.events.list('credit_abc123')
      - lang: bash
        label: Spree CLI
        source: spree api get /store_credits/{store_credit_id}/events
      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
        description: Page number
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        description: Number of records per page
        schema:
          type: integer
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: StoreCreditEvent
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: events found
          content:
            application/json:
              example:
                data:
                - id: scevt_UkLWZg9DAJ
                  action: allocation
                  authorization_code: 1-SC-20260115120000000000
                  display_action: Added
                  amount: '50.00'
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  store_credit_id: credit_UkLWZg9DAJ
                  originator_type:
                  originator_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/StoreCreditEvent"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/variants/{variant_id}/custom_fields":
    get:
      summary: List variant custom fields
      tags:
      - Variants
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the variant'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.variants.customFields.list('variant_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /variants/{variant_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: variant_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/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 default 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_levels'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /products/{product_id}/variants -d '{"expand":["prices","stock_levels"]}'
      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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches SKU, option value or product name (partial, case-insensitive;
          at least three characters).
      - name: q[available_at_stock_location]
        in: query
        required: false
        schema:
          type: string
        description: Applies `available_at_stock_location` to the given value.
      - name: q[product_name_or_sku_cont]
        in: query
        required: false
        schema:
          type: string
        description: Applies `product_name_or_sku_cont` to the given value.
      - name: q[search_by_product_name_or_sku]
        in: query
        required: false
        schema:
          type: string
        description: Applies `search_by_product_name_or_sku` to the given value.
      - 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_levels, 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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[hs_code_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `carton_package_type_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `carton_weight` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `cartons_per_pallet` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `cost_currency` | One of the `CurrencyCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `cost_price` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `country_of_origin` | One of the `CountryCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `deleted_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `depth` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `discontinue_on` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `height` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `hs_code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `minimum_order_quantity` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `order_multiple` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `product_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `purchase_unit` | One of `unit`, `carton` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `sku` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `track_inventory` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `units_per_carton` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `weight` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `width` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[option_values_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `option_values_` | `created_at`, `id`, `label`, `name`, `position`, `updated_at` |
          | `prices_` | `amount`, `compare_at_amount`, `created_at`, `currency`, `id`, `min_quantity`, `price_list_id`, `updated_at`, `variant_id` |
          | `prices_price_list_` | `catalog_id`, `created_at`, `ends_at`, `id`, `match_policy`, `name`, `position`, `starts_at`, `status`, `updated_at` |
          | `product_` | `available_on`, `created_at`, `description`, `discontinue_on`, `id`, `name`, `price`, `seller_id`, `slug`, `status`, `updated_at` |
          | `product_categories_` | `automatic`, `children_count`, `created_at`, `depth`, `id`, `name`, `parent_id`, `permalink`, `position`, `pretty_name`, `products_count`, `updated_at` |
          | `product_channels_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `product_collections_` | `automatic`, `created_at`, `id`, `name`, `permalink`, `position`, `products_count`, `sort_order`, `updated_at` |
          | `product_labels_` | `created_at`, `id`, `name`, `updated_at` |
          | `product_option_types_` | `created_at`, `id`, `kind`, `label`, `name`, `position`, `updated_at` |
          | `product_product_categories_` | `category_id`, `created_at`, `id`, `position`, `product_id`, `updated_at` |
          | `product_product_type_` | `created_at`, `id`, `name`, `updated_at` |
          | `product_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `product_store_` | `created_at`, `id`, `name`, `updated_at` |
          | `product_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |

          </Accordion>

          **Sort by:** `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Variant
        sortable:
        - carton_package_type_id
        - carton_weight
        - cartons_per_pallet
        - cost_currency
        - cost_price
        - country_of_origin
        - created_at
        - deleted_at
        - depth
        - discontinue_on
        - height
        - hs_code
        - id
        - minimum_order_quantity
        - order_multiple
        - position
        - product_id
        - purchase_unit
        - sku
        - track_inventory
        - units_per_carton
        - updated_at
        - weight
        - width
      responses:
        '200':
          description: variants found
          content:
            application/json:
              example:
                data:
                - id: variant_UkLWZg9DAJ
                  product_id: prod_UkLWZg9DAJ
                  sku: SKU-312
                  options_text: ''
                  track_inventory: true
                  media_count: 0
                  preorder_ships_at:
                  thumbnail_url:
                  purchasable: true
                  in_stock: false
                  backorderable: true
                  preorder: false
                  weight: 0.0
                  height:
                  width:
                  depth:
                  weight_unit: lb
                  dimensions_unit: in
                  minimum_order_quantity:
                  order_multiple:
                  purchase_unit:
                  units_per_carton:
                  price:
                    id: price_UkLWZg9DAJ
                    currency: USD
                    amount: '19.99'
                    compare_at_amount:
                    price_list_id:
                    min_quantity: 1
                    variant_id: variant_UkLWZg9DAJ
                    created_at: '2026-01-15T12:00:00.000Z'
                    updated_at: '2026-01-15T12:00:00.000Z'
                  original_price:
                  seller_id:
                  option_values: []
                  external_references: {}
                  metadata: {}
                  position: 1
                  cost_currency: USD
                  barcode:
                  backorder_limit:
                  hs_code:
                  country_of_origin:
                  customs_description:
                  carton_weight:
                  cartons_per_pallet:
                  deleted_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  cost_price: '17.00'
                  preorderable: false
                  tax_category_id:
                  carton_package_type_id:
                  units_per_pallet:
                  available_stock: 0
                  reserved_quantity: 0
                  total_on_hand: 0
                  product_name: Product 2396804
                  delivery_profile_id: fp_UkLWZg9DAJ
                - id: variant_gbHJdmfrXB
                  product_id: prod_UkLWZg9DAJ
                  sku: SKU-313
                  options_text: 'Size: S'
                  track_inventory: true
                  media_count: 0
                  preorder_ships_at:
                  thumbnail_url:
                  purchasable: true
                  in_stock: false
                  backorderable: true
                  preorder: false
                  weight: 198.7
                  height: 97.29
                  width: 126.5
                  depth: 56.58
                  weight_unit: lb
                  dimensions_unit: in
                  minimum_order_quantity:
                  order_multiple:
                  purchase_unit:
                  units_per_carton:
                  price:
                    id: price_gbHJdmfrXB
                    currency: USD
                    amount: '19.99'
                    compare_at_amount:
                    price_list_id:
                    min_quantity: 1
                    variant_id: variant_gbHJdmfrXB
                    created_at: '2026-01-15T12:00:00.000Z'
                    updated_at: '2026-01-15T12:00:00.000Z'
                  original_price:
                  seller_id:
                  option_values:
                  - id: optval_UkLWZg9DAJ
                    option_type_id: opt_UkLWZg9DAJ
                    name: size-72
                    label: S
                    position: 1
                    color_code:
                    option_type_name: foo-size-82
                    option_type_label: Size
                    image_url:
                    metadata: {}
                    created_at: '2026-01-15T12:00:00.000Z'
                    updated_at: '2026-01-15T12:00:00.000Z'
                  external_references: {}
                  metadata: {}
                  position: 2
                  cost_currency: USD
                  barcode:
                  backorder_limit:
                  hs_code:
                  country_of_origin:
                  customs_description:
                  carton_weight:
                  cartons_per_pallet:
                  deleted_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  cost_price: '17.00'
                  preorderable: false
                  tax_category_id:
                  carton_package_type_id:
                  units_per_pallet:
                  available_stock: 0
                  reserved_quantity: 0
                  total_on_hand: 0
                  product_name: Product 2396804
                  delivery_profile_id: fp_UkLWZg9DAJ
                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_levels: [{ stock_location_id: 'sloc_UkLWZg9DAJ', count_on_hand: 25 }],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /products/{product_id}/variants -d '{"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_levels":[{"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
                preorder_ships_at:
                thumbnail_url:
                purchasable: false
                in_stock: false
                backorderable: false
                preorder: false
                weight: 0.0
                height:
                width:
                depth:
                weight_unit: lb
                dimensions_unit: in
                minimum_order_quantity:
                order_multiple:
                purchase_unit:
                units_per_carton:
                price:
                  id: price_EfhxLZ9ck8
                  currency: USD
                  amount: '24.99'
                  compare_at_amount:
                  price_list_id:
                  min_quantity: 1
                  variant_id: variant_EfhxLZ9ck8
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                original_price:
                seller_id:
                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-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                external_references: {}
                metadata: {}
                position: 3
                cost_currency: USD
                barcode:
                backorder_limit:
                hs_code:
                country_of_origin:
                customs_description:
                carton_weight:
                cartons_per_pallet:
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                cost_price:
                preorderable: false
                tax_category_id:
                carton_package_type_id:
                units_per_pallet:
                available_stock: 0
                reserved_quantity: 0
                total_on_hand: 0
                product_name: Product 2401771
                delivery_profile_id: fp_UkLWZg9DAJ
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: SKU has already been taken
                  details:
                    sku:
                    - value: SKU-317
                      code: taken
                      message: has already been taken
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/VariantCreateParams"
        required: true
  "/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_levels'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /products/{product_id}/variants/{id} -d '{"expand":["prices","stock_levels"]}'
      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_levels, 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-319
                options_text: 'Size: S'
                track_inventory: true
                media_count: 0
                preorder_ships_at:
                thumbnail_url:
                purchasable: true
                in_stock: false
                backorderable: true
                preorder: false
                weight: 19.33
                height: 158.93
                width: 166.27
                depth: 20.71
                weight_unit: lb
                dimensions_unit: in
                minimum_order_quantity:
                order_multiple:
                purchase_unit:
                units_per_carton:
                price:
                  id: price_gbHJdmfrXB
                  currency: USD
                  amount: '19.99'
                  compare_at_amount:
                  price_list_id:
                  min_quantity: 1
                  variant_id: variant_gbHJdmfrXB
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                original_price:
                seller_id:
                option_values:
                - id: optval_UkLWZg9DAJ
                  option_type_id: opt_UkLWZg9DAJ
                  name: size-75
                  label: S
                  position: 1
                  color_code:
                  option_type_name: foo-size-85
                  option_type_label: Size
                  image_url:
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                external_references: {}
                metadata: {}
                position: 2
                cost_currency: USD
                barcode:
                backorder_limit:
                hs_code:
                country_of_origin:
                customs_description:
                carton_weight:
                cartons_per_pallet:
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                cost_price: '17.00'
                preorderable: false
                tax_category_id:
                carton_package_type_id:
                units_per_pallet:
                available_stock: 0
                reserved_quantity: 0
                total_on_hand: 0
                product_name: Product 2424025
                delivery_profile_id: fp_UkLWZg9DAJ
        '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_levels: [{ stock_location_id: 'sloc_UkLWZg9DAJ', count_on_hand: 75 }],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /products/{product_id}/variants/{id} -d '{"sku":"UPDATED-SKU","stock_levels":[{"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
                preorder_ships_at:
                thumbnail_url:
                purchasable: true
                in_stock: false
                backorderable: true
                preorder: false
                weight: 85.5
                height: 120.69
                width: 57.61
                depth: 3.72
                weight_unit: lb
                dimensions_unit: in
                minimum_order_quantity:
                order_multiple:
                purchase_unit:
                units_per_carton:
                price:
                  id: price_gbHJdmfrXB
                  currency: USD
                  amount: '19.99'
                  compare_at_amount:
                  price_list_id:
                  min_quantity: 1
                  variant_id: variant_gbHJdmfrXB
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                original_price:
                seller_id:
                option_values:
                - id: optval_UkLWZg9DAJ
                  option_type_id: opt_UkLWZg9DAJ
                  name: size-77
                  label: S
                  position: 1
                  color_code:
                  option_type_name: foo-size-87
                  option_type_label: Size
                  image_url:
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                external_references: {}
                metadata: {}
                position: 2
                cost_currency: USD
                barcode:
                backorder_limit:
                hs_code:
                country_of_origin:
                customs_description:
                carton_weight:
                cartons_per_pallet:
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                cost_price: '17.00'
                preorderable: false
                tax_category_id:
                carton_package_type_id:
                units_per_pallet:
                available_stock: 0
                reserved_quantity: 0
                total_on_hand: 0
                product_name: Product 2445672
                delivery_profile_id: fp_UkLWZg9DAJ
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/VariantUpdateParams"
        required: true
    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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /products/{product_id}/variants/{id}
      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/variants":
    get:
      summary: List variants
      tags:
      - Variants
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns every variant in the store across all products, for pickers and stock views that are not tied to one product.

        **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',
          })

          // Every variant in the store, across all products.
          const { data: variants } = await client.variants.list({
            sku_cont: 'TSHIRT',
            limit: 25,
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /variants -d '{"sku_cont":"TSHIRT","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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches SKU, option value or product name (partial, case-insensitive;
          at least three characters).
      - name: q[available_at_stock_location]
        in: query
        required: false
        schema:
          type: string
        description: Applies `available_at_stock_location` to the given value.
      - name: q[product_name_or_sku_cont]
        in: query
        required: false
        schema:
          type: string
        description: Applies `product_name_or_sku_cont` to the given value.
      - name: q[search_by_product_name_or_sku]
        in: query
        required: false
        schema:
          type: string
        description: Applies `search_by_product_name_or_sku` to the given value.
      - 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: order_id
        in: query
        required: false
        description: 'A draft order to sell to: lists only what its buyer can be sold
          on its channel, priced in its market. Needs `read_orders`, and cannot be
          combined with the fields below.'
        schema:
          type: string
      - name: market_id
        in: query
        required: false
        description: Prices in this market and lists only variants with a price in
          its currency.
        schema:
          type: string
      - name: channel_id
        in: query
        required: false
        description: Lists only variants published on this channel. When a market,
          customer, company or currency is given without it, the store default channel
          applies; an order uses its own.
        schema:
          type: string
      - name: customer_id
        in: query
        required: false
        description: Narrows to the customer's catalogs and prices as they would pay.
          Needs `read_customers`.
        schema:
          type: string
      - name: company_id
        in: query
        required: false
        description: Narrows to the company's catalogs and prices under its agreement.
          Needs `read_customers`.
        schema:
          type: string
      - name: currency
        in: query
        required: false
        description: Lists only variants with a price in this currency. With `market_id`
          it must be the market's currency.
        schema:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[hs_code_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `carton_package_type_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `carton_weight` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `cartons_per_pallet` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `cost_currency` | One of the `CurrencyCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `cost_price` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `country_of_origin` | One of the `CountryCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `deleted_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `depth` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `discontinue_on` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `height` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `hs_code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `minimum_order_quantity` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `order_multiple` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `product_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `purchase_unit` | One of `unit`, `carton` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `sku` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `track_inventory` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `units_per_carton` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `weight` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `width` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[option_values_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `option_values_` | `created_at`, `id`, `label`, `name`, `position`, `updated_at` |
          | `prices_` | `amount`, `compare_at_amount`, `created_at`, `currency`, `id`, `min_quantity`, `price_list_id`, `updated_at`, `variant_id` |
          | `prices_price_list_` | `catalog_id`, `created_at`, `ends_at`, `id`, `match_policy`, `name`, `position`, `starts_at`, `status`, `updated_at` |
          | `product_` | `available_on`, `created_at`, `description`, `discontinue_on`, `id`, `name`, `price`, `seller_id`, `slug`, `status`, `updated_at` |
          | `product_categories_` | `automatic`, `children_count`, `created_at`, `depth`, `id`, `name`, `parent_id`, `permalink`, `position`, `pretty_name`, `products_count`, `updated_at` |
          | `product_channels_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `product_collections_` | `automatic`, `created_at`, `id`, `name`, `permalink`, `position`, `products_count`, `sort_order`, `updated_at` |
          | `product_labels_` | `created_at`, `id`, `name`, `updated_at` |
          | `product_option_types_` | `created_at`, `id`, `kind`, `label`, `name`, `position`, `updated_at` |
          | `product_product_categories_` | `category_id`, `created_at`, `id`, `position`, `product_id`, `updated_at` |
          | `product_product_type_` | `created_at`, `id`, `name`, `updated_at` |
          | `product_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `product_store_` | `created_at`, `id`, `name`, `updated_at` |
          | `product_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |

          </Accordion>

          **Sort by:** `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Variant
        sortable:
        - carton_package_type_id
        - carton_weight
        - cartons_per_pallet
        - cost_currency
        - cost_price
        - country_of_origin
        - created_at
        - deleted_at
        - depth
        - discontinue_on
        - height
        - hs_code
        - id
        - minimum_order_quantity
        - order_multiple
        - position
        - product_id
        - purchase_unit
        - sku
        - track_inventory
        - units_per_carton
        - updated_at
        - weight
        - width
      responses:
        '200':
          description: variants found
          content:
            application/json:
              example:
                data:
                - id: variant_UkLWZg9DAJ
                  product_id: prod_UkLWZg9DAJ
                  sku: SKU-326
                  options_text: ''
                  track_inventory: true
                  media_count: 0
                  preorder_ships_at:
                  thumbnail_url:
                  purchasable: true
                  in_stock: false
                  backorderable: true
                  preorder: false
                  weight: 0.0
                  height:
                  width:
                  depth:
                  weight_unit: lb
                  dimensions_unit: in
                  minimum_order_quantity:
                  order_multiple:
                  purchase_unit:
                  units_per_carton:
                  price:
                    id: price_UkLWZg9DAJ
                    currency: USD
                    amount: '19.99'
                    compare_at_amount:
                    price_list_id:
                    min_quantity: 1
                    variant_id: variant_UkLWZg9DAJ
                    created_at: '2026-01-15T12:00:00.000Z'
                    updated_at: '2026-01-15T12:00:00.000Z'
                  original_price:
                  seller_id:
                  option_values: []
                  external_references: {}
                  metadata: {}
                  position: 1
                  cost_currency: USD
                  barcode:
                  backorder_limit:
                  hs_code:
                  country_of_origin:
                  customs_description:
                  carton_weight:
                  cartons_per_pallet:
                  deleted_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  cost_price: '17.00'
                  preorderable: false
                  tax_category_id:
                  carton_package_type_id:
                  units_per_pallet:
                  available_stock: 0
                  reserved_quantity: 0
                  total_on_hand: 0
                  product_name: Product 2463647
                  delivery_profile_id: fp_UkLWZg9DAJ
                - id: variant_gbHJdmfrXB
                  product_id: prod_UkLWZg9DAJ
                  sku: SKU-327
                  options_text: 'Size: S'
                  track_inventory: true
                  media_count: 0
                  preorder_ships_at:
                  thumbnail_url:
                  purchasable: true
                  in_stock: false
                  backorderable: true
                  preorder: false
                  weight: 138.91
                  height: 145.43
                  width: 8.97
                  depth: 6.25
                  weight_unit: lb
                  dimensions_unit: in
                  minimum_order_quantity:
                  order_multiple:
                  purchase_unit:
                  units_per_carton:
                  price:
                    id: price_gbHJdmfrXB
                    currency: USD
                    amount: '19.99'
                    compare_at_amount:
                    price_list_id:
                    min_quantity: 1
                    variant_id: variant_gbHJdmfrXB
                    created_at: '2026-01-15T12:00:00.000Z'
                    updated_at: '2026-01-15T12:00:00.000Z'
                  original_price:
                  seller_id:
                  option_values:
                  - id: optval_UkLWZg9DAJ
                    option_type_id: opt_UkLWZg9DAJ
                    name: size-79
                    label: S
                    position: 1
                    color_code:
                    option_type_name: foo-size-89
                    option_type_label: Size
                    image_url:
                    metadata: {}
                    created_at: '2026-01-15T12:00:00.000Z'
                    updated_at: '2026-01-15T12:00:00.000Z'
                  external_references: {}
                  metadata: {}
                  position: 2
                  cost_currency: USD
                  barcode:
                  backorder_limit:
                  hs_code:
                  country_of_origin:
                  customs_description:
                  carton_weight:
                  cartons_per_pallet:
                  deleted_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  cost_price: '17.00'
                  preorderable: false
                  tax_category_id:
                  carton_package_type_id:
                  units_per_pallet:
                  available_stock: 0
                  reserved_quantity: 0
                  total_on_hand: 0
                  product_name: Product 2463647
                  delivery_profile_id: fp_UkLWZg9DAJ
                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/Variant"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /webhook_endpoints/{webhook_endpoint_id}/deliveries
      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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of event name (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - 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
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[event_name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `delivered_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `event_name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `execution_time` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `response_code` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `success` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `delivered_at`, `event_name`, `execution_time`, `id`, `response_code`, `success`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: WebhookDelivery
        sortable:
        - created_at
        - delivered_at
        - event_name
        - execution_time
        - id
        - response_code
        - success
        - updated_at
      responses:
        '200':
          description: deliveries found
          content:
            application/json:
              example:
                data:
                - id: whd_UkLWZg9DAJ
                  event_name: order.created
                  event_id:
                  response_code: 200
                  execution_time: 150
                  error_type:
                  request_errors:
                  response_body:
                  success: true
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  delivered_at: '2026-01-15T12:00:00.000Z'
                  payload:
                    event: order.created
                    data:
                      id: 1
                  webhook_endpoint_id: whe_UkLWZg9DAJ
                  webhook_endpoint_url: https://shop.example.com/webhooks
                - id: whd_gbHJdmfrXB
                  event_name: order.created
                  event_id:
                  response_code: 500
                  execution_time: 200
                  error_type:
                  request_errors:
                  response_body:
                  success: false
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  delivered_at: '2026-01-15T12:00:00.000Z'
                  payload:
                    event: order.created
                    data:
                      id: 1
                  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')
      - lang: bash
        label: Spree CLI
        source: spree api get /webhook_endpoints/{webhook_endpoint_id}/deliveries/{id}
      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
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivered_at: '2026-01-15T12:00:00.000Z'
                payload:
                  event: order.created
                  data:
                    id: 1
                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')
      - lang: bash
        label: Spree CLI
        source: spree api post /webhook_endpoints/{webhook_endpoint_id}/deliveries/{id}/redeliver
          -d '{ ... }'
      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:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivered_at:
                payload:
                  event: order.created
                  data:
                    id: 1
                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()
      - lang: bash
        label: Spree CLI
        source: spree api get /webhook_endpoints
      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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of url (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - 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
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `active` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `url` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |

          **Sort by:** `active`, `created_at`, `id`, `name`, `updated_at`, `url`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: WebhookEndpoint
        sortable:
        - active
        - created_at
        - id
        - name
        - updated_at
        - url
      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-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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.placed', '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
      - lang: bash
        label: Spree CLI
        source: spree api post /webhook_endpoints -d '{"name":"Order pipeline","url":"https://example.com/webhooks/orders","active":true,"subscriptions":["order.placed","order.canceled"]}'
      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.placed
                disabled_reason:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                disabled_at:
                secret_key: f44b508d518f47b9d42ae8a67ba913f7f7c4ee25be2e4dda1fbc06370fe29854
                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 must be a valid http or https URL
                  details:
                    url:
                    - value: not a url
                      code: invalid
                      message: must be a valid http or https URL
                      specific: true
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/WebhookEndpointCreateParams"
        required: true
  "/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')
      - lang: bash
        label: Spree CLI
        source: spree api get /webhook_endpoints/{id}
      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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                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.placed', 'order.canceled', 'order.paid'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /webhook_endpoints/{id} -d '{"name":"Order pipeline
          (v2)","subscriptions":["order.placed","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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                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 must be a valid http or https URL
                  details:
                    url:
                    - value: not a url
                      code: invalid
                      message: must be a valid http or https URL
                      specific: true
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/WebhookEndpointUpdateParams"
        required: true
    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')
      - lang: bash
        label: Spree CLI
        source: spree api delete /webhook_endpoints/{id}
      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')
      - lang: bash
        label: Spree CLI
        source: spree api post /webhook_endpoints/{id}/send_test -d '{ ... }'
      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:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivered_at:
                payload:
                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')
      - lang: bash
        label: Spree CLI
        source: spree api patch /webhook_endpoints/{id}/enable -d '{ ... }'
      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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                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',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /webhook_endpoints/{id}/disable -d '{"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-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                disabled_at: '2026-01-15T12:00:00.000Z'
                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:
              "$ref": "#/components/schemas/WebhookEndpointDisableParams"
        required: true
  "/api/v3/admin/webhook_events":
    get:
      summary: List webhook events
      tags:
      - Webhooks
      security:
      - api_key: []
        bearer_auth: []
      description: Returns every event a webhook endpoint can subscribe to, including
        those installed extensions declare. Credential events reach only endpoints
        that name them, and subscribing to one needs the permission listed; deprecated
        events name their replacement.
      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: events } = await client.webhookEvents.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /webhook_events
      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: events returned
          content:
            application/json:
              example:
                data:
                - name: admin_user.password_reset
                  group: admin_user
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: cart.created
                  group: cart
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: cart.deleted
                  group: cart
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: cart.updated
                  group: cart
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: catalog.created
                  group: catalog
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: catalog.deleted
                  group: catalog
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: catalog.updated
                  group: catalog
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: claim.approved
                  group: claim
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: claim.canceled
                  group: claim
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: claim.created
                  group: claim
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: claim.deleted
                  group: claim
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: claim.denied
                  group: claim
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: claim.opened
                  group: claim
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: claim.resolved
                  group: claim
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: claim.updated
                  group: claim
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: company.created
                  group: company
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: company.deleted
                  group: company
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: company.updated
                  group: company
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: company_invitation.accepted
                  group: company_invitation
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: company_invitation.created
                  group: company_invitation
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: company_invitation.deleted
                  group: company_invitation
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: company_invitation.revoked
                  group: company_invitation
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: company_invitation.updated
                  group: company_invitation
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: customer.anonymized
                  group: customer
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: customer.password_reset
                  group: customer
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: customer.password_reset_requested
                  group: customer
                  credential_permission: write_customers
                  credential: true
                  deprecated: false
                  replaced_by:
                - name: data_request.completed
                  group: data_request
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: data_request.confirmation_requested
                  group: data_request
                  credential_permission: write_customers
                  credential: true
                  deprecated: false
                  replaced_by:
                - name: data_request.created
                  group: data_request
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: data_request.deleted
                  group: data_request
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: data_request.updated
                  group: data_request
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: delivery.created
                  group: delivery
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: delivery.deleted
                  group: delivery
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: delivery.updated
                  group: delivery
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: digital.created
                  group: digital
                  credential_permission:
                  credential: false
                  deprecated: true
                  replaced_by: digital_asset.created
                - name: digital.deleted
                  group: digital
                  credential_permission:
                  credential: false
                  deprecated: true
                  replaced_by: digital_asset.deleted
                - name: digital.updated
                  group: digital
                  credential_permission:
                  credential: false
                  deprecated: true
                  replaced_by: digital_asset.updated
                - name: digital_asset.created
                  group: digital_asset
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: digital_asset.deleted
                  group: digital_asset
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: digital_asset.updated
                  group: digital_asset
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: digital_link.created
                  group: digital_link
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: digital_link.deleted
                  group: digital_link
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: digital_link.downloaded
                  group: digital_link
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: digital_link.updated
                  group: digital_link
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: email_template.published
                  group: email_template
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: email_template.reverted
                  group: email_template
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: exchange.approved
                  group: exchange
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: exchange.canceled
                  group: exchange
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: exchange.created
                  group: exchange
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: exchange.deleted
                  group: exchange
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: exchange.fulfilled
                  group: exchange
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: exchange.received
                  group: exchange
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: exchange.requested
                  group: exchange
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: exchange.updated
                  group: exchange
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: export.created
                  group: export
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: export.deleted
                  group: export
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: export.updated
                  group: export
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: fulfillment.canceled
                  group: fulfillment
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: fulfillment.created
                  group: fulfillment
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: fulfillment.deleted
                  group: fulfillment
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: fulfillment.delivered
                  group: fulfillment
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: fulfillment.fulfilled
                  group: fulfillment
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: fulfillment.updated
                  group: fulfillment
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: gift_card.canceled
                  group: gift_card
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: gift_card.created
                  group: gift_card
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: gift_card.deleted
                  group: gift_card
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: gift_card.partially_redeemed
                  group: gift_card
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: gift_card.redeemed
                  group: gift_card
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: gift_card.updated
                  group: gift_card
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: gift_card_batch.created
                  group: gift_card_batch
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: gift_card_batch.deleted
                  group: gift_card_batch
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: gift_card_batch.updated
                  group: gift_card_batch
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: import.completed
                  group: import
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: import.created
                  group: import
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: import.deleted
                  group: import
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: import.progress
                  group: import
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: import.updated
                  group: import
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: import_row.completed
                  group: import_row
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: import_row.failed
                  group: import_row
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: invitation.accepted
                  group: invitation
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: invitation.created
                  group: invitation
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: invitation.resent
                  group: invitation
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: line_item.created
                  group: line_item
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: line_item.deleted
                  group: line_item
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: line_item.updated
                  group: line_item
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: maintenance_task_run.cancelled
                  group: maintenance_task_run
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: maintenance_task_run.created
                  group: maintenance_task_run
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: maintenance_task_run.deleted
                  group: maintenance_task_run
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: maintenance_task_run.errored
                  group: maintenance_task_run
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: maintenance_task_run.interrupted
                  group: maintenance_task_run
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: maintenance_task_run.started
                  group: maintenance_task_run
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: maintenance_task_run.succeeded
                  group: maintenance_task_run
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: maintenance_task_run.updated
                  group: maintenance_task_run
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: media.created
                  group: media
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: media.deleted
                  group: media
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: media.updated
                  group: media
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: newsletter_subscriber.created
                  group: newsletter_subscriber
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: newsletter_subscriber.deleted
                  group: newsletter_subscriber
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: newsletter_subscriber.subscription_requested
                  group: newsletter_subscriber
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: newsletter_subscriber.unsubscribe_requested
                  group: newsletter_subscriber
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: newsletter_subscriber.updated
                  group: newsletter_subscriber
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: newsletter_subscriber.verified
                  group: newsletter_subscriber
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order.approved
                  group: order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order.canceled
                  group: order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order.completed
                  group: order
                  credential_permission:
                  credential: false
                  deprecated: true
                  replaced_by: order.placed
                - name: order.created
                  group: order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order.deleted
                  group: order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order.delivered
                  group: order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order.fulfilled
                  group: order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order.paid
                  group: order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order.placed
                  group: order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order.resend_confirmation_email
                  group: order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order.resend_digital_links_email
                  group: order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order.shipped
                  group: order
                  credential_permission:
                  credential: false
                  deprecated: true
                  replaced_by: order.fulfilled
                - name: order.updated
                  group: order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order_group.completed
                  group: order_group
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order_group.created
                  group: order_group
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order_group.deleted
                  group: order_group
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order_group.resend_confirmation_email
                  group: order_group
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: order_group.updated
                  group: order_group
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment.captured
                  group: payment
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment.completed
                  group: payment
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment.created
                  group: payment
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment.deleted
                  group: payment
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment.paid
                  group: payment
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment.refunded
                  group: payment
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment.updated
                  group: payment
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment.voided
                  group: payment
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_session.canceled
                  group: payment_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_session.completed
                  group: payment_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_session.created
                  group: payment_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_session.deleted
                  group: payment_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_session.expired
                  group: payment_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_session.failed
                  group: payment_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_session.processing
                  group: payment_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_session.updated
                  group: payment_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_setup_session.canceled
                  group: payment_setup_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_setup_session.completed
                  group: payment_setup_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_setup_session.created
                  group: payment_setup_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_setup_session.deleted
                  group: payment_setup_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_setup_session.expired
                  group: payment_setup_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_setup_session.failed
                  group: payment_setup_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_setup_session.processing
                  group: payment_setup_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: payment_setup_session.updated
                  group: payment_setup_session
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: price.created
                  group: price
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: price.deleted
                  group: price
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: price.updated
                  group: price
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product.activated
                  group: product
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product.approved
                  group: product
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product.archived
                  group: product
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product.back_in_stock
                  group: product
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product.created
                  group: product
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product.deleted
                  group: product
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product.drafted
                  group: product
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product.out_of_stock
                  group: product
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product.proposed
                  group: product
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product.rejected
                  group: product
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product.updated
                  group: product
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product_category.created
                  group: product_category
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product_category.deleted
                  group: product_category
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product_collection.created
                  group: product_collection
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product_collection.deleted
                  group: product_collection
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product_submission.created
                  group: product_submission
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product_submission.deleted
                  group: product_submission
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: product_submission.updated
                  group: product_submission
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: promotion.created
                  group: promotion
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: promotion.deleted
                  group: promotion
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: promotion.updated
                  group: promotion
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: purchase_order.canceled
                  group: purchase_order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: purchase_order.created
                  group: purchase_order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: purchase_order.deleted
                  group: purchase_order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: purchase_order.draft
                  group: purchase_order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: purchase_order.ordered
                  group: purchase_order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: purchase_order.over_received
                  group: purchase_order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: purchase_order.partially_received
                  group: purchase_order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: purchase_order.received
                  group: purchase_order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: purchase_order.updated
                  group: purchase_order
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: refund.created
                  group: refund
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: refund.deleted
                  group: refund
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: refund.updated
                  group: refund
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: return.approved
                  group: return
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: return.canceled
                  group: return
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: return.created
                  group: return
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: return.deleted
                  group: return
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: return.received
                  group: return
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: return.refunded
                  group: return
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: return.requested
                  group: return
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: return.updated
                  group: return
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: saved_report.created
                  group: saved_report
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: saved_report.deleted
                  group: saved_report
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: saved_report.updated
                  group: saved_report
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller.approved
                  group: seller
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller.created
                  group: seller
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller.deleted
                  group: seller
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller.invited
                  group: seller
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller.onboarding_reopened
                  group: seller
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller.onboarding_started
                  group: seller
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller.rejected
                  group: seller
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller.submitted_for_review
                  group: seller
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller.suspended
                  group: seller
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller.updated
                  group: seller
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller_payout.completed
                  group: seller_payout
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller_requirement_submission.accepted
                  group: seller_requirement_submission
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller_requirement_submission.created
                  group: seller_requirement_submission
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller_requirement_submission.deleted
                  group: seller_requirement_submission
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller_requirement_submission.rejected
                  group: seller_requirement_submission
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller_requirement_submission.updated
                  group: seller_requirement_submission
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller_requirement_submission.waived
                  group: seller_requirement_submission
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: seller_user.password_reset
                  group: seller_user
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: shipment.canceled
                  group: shipment
                  credential_permission:
                  credential: false
                  deprecated: true
                  replaced_by: fulfillment.canceled
                - name: shipment.shipped
                  group: shipment
                  credential_permission:
                  credential: false
                  deprecated: true
                  replaced_by: fulfillment.fulfilled
                - name: shipping_label.created
                  group: shipping_label
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: shipping_label.deleted
                  group: shipping_label
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: shipping_label.purchased
                  group: shipping_label
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: shipping_label.refunded
                  group: shipping_label
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: shipping_label.updated
                  group: shipping_label
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_item.created
                  group: stock_item
                  credential_permission:
                  credential: false
                  deprecated: true
                  replaced_by: stock_level.created
                - name: stock_item.deleted
                  group: stock_item
                  credential_permission:
                  credential: false
                  deprecated: true
                  replaced_by: stock_level.deleted
                - name: stock_item.updated
                  group: stock_item
                  credential_permission:
                  credential: false
                  deprecated: true
                  replaced_by: stock_level.updated
                - name: stock_level.created
                  group: stock_level
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_level.deleted
                  group: stock_level
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_level.updated
                  group: stock_level
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_movement.created
                  group: stock_movement
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_movement.deleted
                  group: stock_movement
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_movement.updated
                  group: stock_movement
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_receipt.created
                  group: stock_receipt
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_receipt.deleted
                  group: stock_receipt
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_receipt.updated
                  group: stock_receipt
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_reservation.created
                  group: stock_reservation
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_reservation.deleted
                  group: stock_reservation
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_reservation.updated
                  group: stock_reservation
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_transfer.canceled
                  group: stock_transfer
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_transfer.created
                  group: stock_transfer
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_transfer.deleted
                  group: stock_transfer
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_transfer.draft
                  group: stock_transfer
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_transfer.over_received
                  group: stock_transfer
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_transfer.partially_received
                  group: stock_transfer
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_transfer.ready_to_ship
                  group: stock_transfer
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_transfer.received
                  group: stock_transfer
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_transfer.shipped
                  group: stock_transfer
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: stock_transfer.updated
                  group: stock_transfer
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: store_credit.created
                  group: store_credit
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: store_credit.deleted
                  group: store_credit
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: store_credit.updated
                  group: store_credit
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: supplier.created
                  group: supplier
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: supplier.deleted
                  group: supplier
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: supplier.updated
                  group: supplier
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: tax_exemption_certificate.verified
                  group: tax_exemption_certificate
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: tax_identifier.number_changed
                  group: tax_identifier
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: user.created
                  group: user
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: user.deleted
                  group: user
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: user.updated
                  group: user
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: variant.created
                  group: variant
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: variant.deleted
                  group: variant
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: variant.updated
                  group: variant
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: wished_item.created
                  group: wished_item
                  credential_permission:
                  credential: false
                  deprecated: true
                  replaced_by: wishlist_item.created
                - name: wished_item.deleted
                  group: wished_item
                  credential_permission:
                  credential: false
                  deprecated: true
                  replaced_by: wishlist_item.deleted
                - name: wished_item.updated
                  group: wished_item
                  credential_permission:
                  credential: false
                  deprecated: true
                  replaced_by: wishlist_item.updated
                - name: wishlist.created
                  group: wishlist
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: wishlist.deleted
                  group: wishlist
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: wishlist.updated
                  group: wishlist
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: wishlist_item.created
                  group: wishlist_item
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: wishlist_item.deleted
                  group: wishlist_item
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                - name: wishlist_item.updated
                  group: wishlist_item
                  credential_permission:
                  credential: false
                  deprecated: false
                  replaced_by:
                meta:
                  count: 264
  "/api/v3/admin/catalogs":
    get:
      summary: List catalogs
      tags:
      - Catalogs
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the store catalogs — product assortments with an optional price list, shown to audiences through assignments.

        **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: catalogs } = await client.catalogs.list({ active_eq: true })
      - lang: bash
        label: Spree CLI
        source: spree api get /catalogs -d '{"active_eq":true}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `active` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `active`, `created_at`, `id`, `name`, `position`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Catalog
        sortable:
        - active
        - created_at
        - id
        - name
        - position
        - updated_at
      responses:
        '200':
          description: catalogs found
          content:
            application/json:
              example:
                data:
                - id: cat_UkLWZg9DAJ
                  name: Wholesale
                  description:
                  active: true
                  position: 1
                  metadata: {}
                  minimum_order_quantity:
                  order_multiple:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  products_count: 0
                  pricing_strategy: base
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Create a catalog
      tags:
      - Catalogs
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Creates a catalog. Add products and assign audiences (customer group, or company subtree) afterwards.

        **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',
          })

          // The catalog and the price list it charges through are written together, so
          // standing up an agreement never means visiting the price-lists page.
          const catalog = await client.catalogs.create({
            name: 'VIP Assortment',
            price_list: { price_adjustment_percentage: '-15.0' },
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /catalogs -d '{"name":"VIP Assortment","price_list":{"price_adjustment_percentage":"-15.0"}}'
      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: catalog created
          content:
            application/json:
              example:
                id: cat_gbHJdmfrXB
                name: VIP Assortment
                description:
                active: false
                position: 2
                metadata: {}
                minimum_order_quantity:
                order_multiple:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                products_count: 0
                pricing_strategy: base
        '422':
          description: invalid request
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CatalogCreateParams"
        required: true
  "/api/v3/admin/catalogs/{id}":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
    patch:
      summary: Update a catalog
      tags:
      - Catalogs
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Updates a catalog and its commercial terms. Only the attributes sent change.

        **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 catalog = await client.catalogs.update('cat_UkLWZg9DAJ', {
            name: 'Wholesale Plus',
            minimum_order_quantity: 10,
            order_multiple: 5,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /catalogs/{id} -d '{"name":"Wholesale Plus","minimum_order_quantity":10,"order_multiple":5}'
      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: catalog updated
          content:
            application/json:
              example:
                id: cat_UkLWZg9DAJ
                name: Wholesale Plus
                description:
                active: true
                position: 1
                metadata: {}
                minimum_order_quantity: 10
                order_multiple: 5
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                products_count: 0
                pricing_strategy: base
              schema:
                "$ref": "#/components/schemas/Catalog"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CatalogUpdateParams"
        required: true
  "/api/v3/admin/catalogs/{id}/assign":
    post:
      summary: Assign a catalog to an audience
      tags:
      - Catalogs
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Shows the catalog to an audience. A company assignment covers the node and its whole subtree.

        **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',
          })

          // A company assignment covers the node and its whole subtree.
          const assignment = await client.catalogs.assign('cat_86Rf07xd4z', {
            assignable_type: 'company',
            assignable_id: 'comp_86Rf07xd4z',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /catalogs/{id}/assign -d '{"assignable_type":"company","assignable_id":"comp_86Rf07xd4z"}'
      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:
        '201':
          description: catalog assigned
          content:
            application/json:
              example:
                id: cata_UkLWZg9DAJ
                created_at: '2026-01-15T12:00:00.000Z'
                catalog_id: cat_UkLWZg9DAJ
                assignable_type: company
                assignable_id: comp_UkLWZg9DAJ
                assignable_name: Acme Corp 1
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CatalogAssignParams"
        required: true
  "/api/v3/admin/catalogs/{id}/import_products":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
    post:
      summary: Import price list products into a catalog
      tags:
      - Catalogs
      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 { added_count } = await client.catalogs.importProducts('cat_86Rf07xd4z')
      - lang: bash
        label: Spree CLI
        source: spree api post /catalogs/{id}/import_products -d '{ ... }'
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds every product on the catalog's price list to its assortment. Products
        already in it stay, even ones the list does not price. Refused for a
        catalog without a price list; the count reports what was added.


        **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 imported
          content:
            application/json:
              example:
                added_count: 1
              schema:
                type: object
                properties:
                  added_count:
                    type: integer
                required:
                - added_count
        '422':
          description: the catalog has no price list
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: This catalog has no price list to import products from.
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/catalogs/{catalog_id}/products":
    get:
      summary: List catalog products
      tags:
      - Catalogs
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The catalog's curated assortment, listed by product name — membership
        carries no order.

        `expand=catalog_price` adds what a buyer on this agreement pays for
        each row and where the amount comes from: `explicit` (an amount
        entered on the catalog's own price list), `automatic` (that list's
        percentage applied to the shop price) or `base` (the shop price
        itself — this agreement does not price the product).


        **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',
          })

          // `catalog_price` adds what a buyer on this agreement pays for each product.
          const { data: products } = await client.catalogs.products.list('cat_UkLWZg9DAJ', {
            expand: ['catalog_price'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /catalogs/{catalog_id}/products -d '{"expand":["catalog_price"]}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: catalog_id
        in: path
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches product name or variant SKU (partial, case-insensitive),
          and the store's searchable custom fields.
      - name: q[ascend_by_price]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `ascend_by_price`.
      - name: q[descend_by_price]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `descend_by_price`.
      - name: q[in_categories][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        description: Applies `in_categories` to the given value.
      - name: q[in_category]
        in: query
        required: false
        schema:
          type: string
        description: Applies `in_category` to the given value.
      - name: q[in_collection]
        in: query
        required: false
        schema:
          type: string
        description: Applies `in_collection` to the given value.
      - name: q[in_stock]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `in_stock`.
      - name: q[in_taxon]
        in: query
        required: false
        schema:
          type: string
        description: Applies `in_taxon` to the given value.
      - name: q[not_discontinued]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `not_discontinued`.
      - name: q[out_of_stock]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `out_of_stock`.
      - name: q[price_between][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: number
          minItems: 2
          maxItems: 2
        description: Applies `price_between` to the given value.
      - name: q[price_gte]
        in: query
        required: false
        schema:
          type: number
        description: Applies `price_gte` to the given value.
      - name: q[price_lte]
        in: query
        required: false
        schema:
          type: number
        description: Applies `price_lte` to the given value.
      - name: q[search_by_name]
        in: query
        required: false
        schema:
          type: string
        description: Applies `search_by_name` to the given value.
      - name: q[with_option_value_ids][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        description: Applies `with_option_value_ids` to the given value.
      - name: expand
        in: query
        required: false
        description: Comma-separated. `catalog_price` adds the resolved price to every
          row.
        example: catalog_price
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `available_on` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `description` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `discontinue_on` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `price` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `seller_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `slug` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `status` | One of `draft`, `active`, `archived`, `proposed`, `rejected` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[categories_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `categories_` | `automatic`, `children_count`, `created_at`, `depth`, `id`, `name`, `parent_id`, `permalink`, `position`, `pretty_name`, `products_count`, `updated_at` |
          | `categories_parent_` | `automatic`, `children_count`, `created_at`, `depth`, `id`, `name`, `parent_id`, `permalink`, `position`, `pretty_name`, `products_count`, `updated_at` |
          | `channels_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `collections_` | `automatic`, `created_at`, `id`, `name`, `permalink`, `position`, `products_count`, `sort_order`, `updated_at` |
          | `default_variant_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `default_variant_option_values_` | `created_at`, `id`, `label`, `name`, `position`, `updated_at` |
          | `default_variant_prices_` | `amount`, `compare_at_amount`, `created_at`, `currency`, `id`, `min_quantity`, `price_list_id`, `updated_at`, `variant_id` |
          | `default_variant_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `default_variant_tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |
          | `labels_` | `created_at`, `id`, `name`, `updated_at` |
          | `option_types_` | `created_at`, `id`, `kind`, `label`, `name`, `position`, `updated_at` |
          | `product_categories_` | `category_id`, `created_at`, `id`, `position`, `product_id`, `updated_at` |
          | `product_type_` | `created_at`, `id`, `name`, `updated_at` |
          | `product_type_option_types_` | `created_at`, `id`, `kind`, `label`, `name`, `position`, `updated_at` |
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `store_` | `created_at`, `id`, `name`, `updated_at` |
          | `tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `variants_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `variants_option_values_` | `created_at`, `id`, `label`, `name`, `position`, `updated_at` |
          | `variants_prices_` | `amount`, `compare_at_amount`, `created_at`, `currency`, `id`, `min_quantity`, `price_list_id`, `updated_at`, `variant_id` |
          | `variants_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `variants_tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |

          </Accordion>

          **Sort by:** `available_on`, `created_at`, `description`, `discontinue_on`, `id`, `name`, `price`, `seller_id`, `slug`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Product
        sortable:
        - available_on
        - created_at
        - description
        - discontinue_on
        - id
        - name
        - price
        - seller_id
        - slug
        - status
        - updated_at
      responses:
        '200':
          description: products found, with what the agreement charges
          content:
            application/json:
              example:
                data:
                - id: prod_UkLWZg9DAJ
                  name: Product 22159
                  thumbnail_url:
                  catalog_variants:
                  - id: variant_UkLWZg9DAJ
                    label:
                    sku: SKU-2
                    currency: USD
                    source: automatic
                    break_count: 0
                    amount: '80.00'
                    tiers: []
                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/CatalogProduct"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Add products to a catalog
      tags:
      - Catalogs
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Curates products into the assortment in bulk. Already-present products are skipped; the count reports what was added.

        **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 { added_count } = await client.catalogs.products.create('cat_UkLWZg9DAJ', [
            'prod_86Rf07xd4z',
            'prod_9XbR2kQwLm',
          ])
      - lang: bash
        label: Spree CLI
        source: spree api post /catalogs/{catalog_id}/products -d '{ ... }'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: catalog_id
        in: path
        required: true
        schema:
          type: string
      responses:
        '201':
          description: products added
          content:
            application/json:
              example:
                added_count: 1
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductMembershipParams"
        required: true
    delete:
      summary: Remove products from a catalog
      tags:
      - Catalogs
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Removes products from the assortment in bulk. Ids that are not members are ignored; the count reports what was removed.

        **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 { removed_count } = await client.catalogs.products.delete('cat_UkLWZg9DAJ', [
            'prod_86Rf07xd4z',
          ])
      - lang: bash
        label: Spree CLI
        source: spree api delete /catalogs/{catalog_id}/products
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: catalog_id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: products removed
          content:
            application/json:
              example:
                removed_count: 1
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductMembershipParams"
        required: true
  "/api/v3/admin/catalogs/{catalog_id}/order_minimums":
    get:
      summary: List catalog order minimums
      tags:
      - Catalogs
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The least a whole order must come to under this agreement. One row per currency — Spree holds no exchange rates, so a threshold is never stated once and converted.

        **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: orderMinimums } = await client.catalogs.orderMinimums.list('cat_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /catalogs/{catalog_id}/order_minimums
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: catalog_id
        in: path
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CatalogOrderMinimum
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: order minimums found
          content:
            application/json:
              example:
                data:
                - id: com_UkLWZg9DAJ
                  currency: USD
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  amount: '500.00'
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Create a catalog order minimum
      tags:
      - Catalogs
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Requires orders in one currency to reach an amount. The buyer sees the shortfall on the cart while they can still act on it; completion is refused below it.

        **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 orderMinimum = await client.catalogs.orderMinimums.create('cat_UkLWZg9DAJ', {
            currency: 'USD',
            amount: '500.00',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /catalogs/{catalog_id}/order_minimums -d '{"currency":"USD","amount":"500.00"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: catalog_id
        in: path
        required: true
        schema:
          type: string
      responses:
        '201':
          description: order minimum created
          content:
            application/json:
              example:
                id: com_UkLWZg9DAJ
                currency: USD
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                amount: '500.00'
        '422':
          description: invalid request
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Amount must be greater than 0
                  details:
                    amount:
                    - value: 0
                      count: 0
                      code: greater_than
                      message: must be greater than 0
                      specific: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CatalogOrderMinimumParams"
        required: true
  "/api/v3/admin/catalogs/{catalog_id}/order_minimums/{id}":
    patch:
      summary: Update a catalog order minimum
      tags:
      - Catalogs
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Restates one currency's threshold.

        **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 orderMinimum = await client.catalogs.orderMinimums.update(
            'cat_UkLWZg9DAJ',
            'com_k5nR8xLqPz',
            { amount: '750.00' },
          )
      - lang: bash
        label: Spree CLI
        source: spree api patch /catalogs/{catalog_id}/order_minimums/{id} -d '{"amount":"750.00"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: catalog_id
        in: path
        required: true
        schema:
          type: string
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: order minimum updated
          content:
            application/json:
              example:
                id: com_UkLWZg9DAJ
                currency: USD
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                amount: '750.00'
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CatalogOrderMinimumParams"
        required: true
    delete:
      summary: Delete a catalog order minimum
      tags:
      - Catalogs
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Lifts the threshold for one currency, so orders in it may come to any total.

        **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.catalogs.orderMinimums.delete('cat_UkLWZg9DAJ', 'com_k5nR8xLqPz')
      - lang: bash
        label: Spree CLI
        source: spree api delete /catalogs/{catalog_id}/order_minimums/{id}
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: catalog_id
        in: path
        required: true
        schema:
          type: string
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '204':
          description: order minimum deleted
  "/api/v3/admin/catalogs/{catalog_id}/quantity_rules":
    put:
      summary: Set catalog quantity rules
      tags:
      - Catalogs
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Writes the given products' quantity terms in one request, keyed by prefixed product id. The stated pair is written to every variant of the product, which is the grain the database keeps them at. Both fields null clears that product's terms; a product not yet in the assortment is added, since a term with nothing to apply to is not a reachable state. Products absent from the payload are left alone — an agreement may name terms for thousands of SKUs. Read them back on the assortment rows: `GET /catalogs/{id}/products?expand=quantity_rule`.

        **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',
          })

          // Keyed by product. Both values null clears that product's terms.
          await client.catalogs.quantityRules.upsert('cat_UkLWZg9DAJ', {
            terms: {
              prod_86Rf07xd4z: { minimum_order_quantity: 48, order_multiple: 24 },
              prod_9XbR2kQwLm: { minimum_order_quantity: null, order_multiple: null },
            },
          })
      - lang: bash
        label: Spree CLI
        source: spree api put /catalogs/{catalog_id}/quantity_rules -d '{"terms":{"prod_86Rf07xd4z":{"minimum_order_quantity":48,"order_multiple":24},"prod_9XbR2kQwLm":{"minimum_order_quantity":null,"order_multiple":null}}}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: catalog_id
        in: path
        required: true
        schema:
          type: string
      responses:
        '204':
          description: quantity rules set
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CatalogProductTermsParams"
        required: true
  "/api/v3/admin/catalogs/{id}/activate":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
    patch:
      summary: Activate a catalog
      tags:
      - Catalogs
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Puts the agreement into effect: its audience starts seeing its
        assortment and paying its prices. Refused for a catalog nobody is
        assigned to, since activating it would reach no buyer — a channel's
        default catalog is reached through the channel instead, so it needs
        no assignment.


        **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',
          })

          // Puts the agreement into effect. Refused for a catalog nobody is assigned
          // to, which would reach no buyer.
          const catalog = await client.catalogs.activate('cat_xxx')
      - lang: bash
        label: Spree CLI
        source: spree api patch /catalogs/{id}/activate -d '{ ... }'
      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: catalog activated
          content:
            application/json:
              example:
                id: cat_UkLWZg9DAJ
                name: Wholesale
                description:
                active: true
                position: 1
                metadata: {}
                minimum_order_quantity:
                order_multiple:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                products_count: 0
                pricing_strategy: base
              schema:
                "$ref": "#/components/schemas/Catalog"
  "/api/v3/admin/catalogs/{id}/deactivate":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
    patch:
      summary: Deactivate a catalog
      tags:
      - Catalogs
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Takes the agreement out of effect. Everything it holds — assignments,
        commercial terms, its price list — survives, so activating again
        resumes exactly what was there.


        **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',
          })

          // Takes it out of effect; its assignments, terms and prices survive.
          const catalog = await client.catalogs.deactivate('cat_xxx')
      - lang: bash
        label: Spree CLI
        source: spree api patch /catalogs/{id}/deactivate -d '{ ... }'
      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: catalog deactivated
          content:
            application/json:
              example:
                id: cat_UkLWZg9DAJ
                name: Wholesale
                description:
                active: false
                position: 1
                metadata: {}
                minimum_order_quantity:
                order_multiple:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                products_count: 0
                pricing_strategy: base
              schema:
                "$ref": "#/components/schemas/Catalog"
  "/api/v3/admin/collections":
    get:
      summary: List collections
      tags:
      - Collections
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a paginated list of the store's collections.

        **Required scope:** `read_collections` (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: collections } = await client.collections.list({
            name_cont: 'Sale',
            limit: 25,
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /collections -d '{"name_cont":"Sale","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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - 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., rules, custom_fields,
          translations).
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `automatic` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `permalink` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `products_count` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `sort_order` | One of `manual`, `best_selling`, `price asc`, `price desc`, `available_on desc`, `available_on asc`, `name asc`, `name desc` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `automatic`, `created_at`, `id`, `name`, `permalink`, `position`, `products_count`, `sort_order`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Collection
        sortable:
        - automatic
        - created_at
        - id
        - name
        - permalink
        - position
        - products_count
        - sort_order
        - updated_at
      responses:
        '200':
          description: collections found
          content:
            application/json:
              example:
                data:
                - id: coll_UkLWZg9DAJ
                  name: Summer Sale
                  permalink: summer-sale
                  position: 1
                  sort_order: manual
                  meta_title:
                  meta_description:
                  meta_keywords:
                  products_count: 0
                  description: ''
                  description_html: ''
                  image_url:
                  square_image_url:
                  automatic: false
                  rules_match_policy: all
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                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/Collection"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Create a collection
      tags:
      - Collections
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Creates a manual or automatic (rule-based) collection. For automatic collections, send the full desired rule set under `rules`.

        **Required scope:** `write_collections` (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',
          })

          // An automatic collection: its products are the ones matching the rules.
          const collection = await client.collections.create({
            name: 'On Sale',
            automatic: true,
            rules_match_policy: 'any',
            rules: [{ type: 'tag', value: 'summer', match_policy: 'contains' }],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /collections -d '{"name":"On Sale","automatic":true,"rules_match_policy":"any","rules":[{"type":"tag","value":"summer","match_policy":"contains"}]}'
      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: collection created
          content:
            application/json:
              example:
                id: coll_gbHJdmfrXB
                name: On Sale
                permalink: on-sale
                position: 2
                sort_order: manual
                meta_title:
                meta_description:
                meta_keywords:
                products_count: 0
                description: ''
                description_html: ''
                image_url:
                square_image_url:
                automatic: true
                rules_match_policy: any
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/Collection"
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CollectionCreateParams"
        required: true
  "/api/v3/admin/collections/{id}":
    get:
      summary: Get a collection
      tags:
      - Collections
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a single collection by ID, including its rules.

        **Required scope:** `read_collections` (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 collection = await client.collections.get('coll_UkLWZg9DAJ', {
            expand: ['rules'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /collections/{id} -d '{"expand":["rules"]}'
      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: Collection ID
        schema:
          type: string
      - name: expand
        in: query
        required: false
        description: Comma-separated associations to expand (e.g., rules, custom_fields,
          translations).
        schema:
          type: string
      responses:
        '200':
          description: collection found
          content:
            application/json:
              example:
                id: coll_UkLWZg9DAJ
                name: Summer Sale
                permalink: summer-sale
                position: 1
                sort_order: manual
                meta_title:
                meta_description:
                meta_keywords:
                products_count: 0
                description: ''
                description_html: ''
                image_url:
                square_image_url:
                automatic: false
                rules_match_policy: all
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/Collection"
        '404':
          description: collection not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Collection not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update a collection
      tags:
      - Collections
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Updates a collection. Send `position` to reorder it within the flat list; send the full `rules` set to sync automatic rules.

        **Required scope:** `write_collections` (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 collection = await client.collections.update('coll_UkLWZg9DAJ', {
            name: 'Winter Sale',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /collections/{id} -d '{"name":"Winter 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: Collection ID
        schema:
          type: string
      responses:
        '200':
          description: collection updated
          content:
            application/json:
              example:
                id: coll_UkLWZg9DAJ
                name: Winter Sale
                permalink: summer-sale
                position: 1
                sort_order: manual
                meta_title:
                meta_description:
                meta_keywords:
                products_count: 0
                description: ''
                description_html: ''
                image_url:
                square_image_url:
                automatic: false
                rules_match_policy: all
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
              schema:
                "$ref": "#/components/schemas/Collection"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CollectionUpdateParams"
        required: true
    delete:
      summary: Delete a collection
      tags:
      - Collections
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Deletes a collection.

        **Required scope:** `write_collections` (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.collections.delete('coll_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /collections/{id}
      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: Collection ID
        schema:
          type: string
      responses:
        '204':
          description: collection deleted
  "/api/v3/admin/collections/{collection_id}/products":
    get:
      summary: List collection products
      tags:
      - Collections
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Products curated in the collection, ordered by their membership position.

        **Required scope:** `read_collections` (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.collections.products.list('coll_UkLWZg9DAJ', {
            limit: 25,
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /collections/{collection_id}/products -d '{"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: collection_id
        in: path
        required: true
        description: Collection ID
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches product name or variant SKU (partial, case-insensitive),
          and the store's searchable custom fields.
      - name: q[ascend_by_price]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `ascend_by_price`.
      - name: q[descend_by_price]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `descend_by_price`.
      - name: q[in_categories][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        description: Applies `in_categories` to the given value.
      - name: q[in_category]
        in: query
        required: false
        schema:
          type: string
        description: Applies `in_category` to the given value.
      - name: q[in_collection]
        in: query
        required: false
        schema:
          type: string
        description: Applies `in_collection` to the given value.
      - name: q[in_stock]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `in_stock`.
      - name: q[in_taxon]
        in: query
        required: false
        schema:
          type: string
        description: Applies `in_taxon` to the given value.
      - name: q[not_discontinued]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `not_discontinued`.
      - name: q[out_of_stock]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `out_of_stock`.
      - name: q[price_between][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: number
          minItems: 2
          maxItems: 2
        description: Applies `price_between` to the given value.
      - name: q[price_gte]
        in: query
        required: false
        schema:
          type: number
        description: Applies `price_gte` to the given value.
      - name: q[price_lte]
        in: query
        required: false
        schema:
          type: number
        description: Applies `price_lte` to the given value.
      - name: q[search_by_name]
        in: query
        required: false
        schema:
          type: string
        description: Applies `search_by_name` to the given value.
      - name: q[with_option_value_ids][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        description: Applies `with_option_value_ids` to the given value.
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `available_on` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `description` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `discontinue_on` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `price` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `seller_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `slug` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `status` | One of `draft`, `active`, `archived`, `proposed`, `rejected` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[categories_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `categories_` | `automatic`, `children_count`, `created_at`, `depth`, `id`, `name`, `parent_id`, `permalink`, `position`, `pretty_name`, `products_count`, `updated_at` |
          | `categories_parent_` | `automatic`, `children_count`, `created_at`, `depth`, `id`, `name`, `parent_id`, `permalink`, `position`, `pretty_name`, `products_count`, `updated_at` |
          | `channels_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `collections_` | `automatic`, `created_at`, `id`, `name`, `permalink`, `position`, `products_count`, `sort_order`, `updated_at` |
          | `default_variant_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `default_variant_option_values_` | `created_at`, `id`, `label`, `name`, `position`, `updated_at` |
          | `default_variant_prices_` | `amount`, `compare_at_amount`, `created_at`, `currency`, `id`, `min_quantity`, `price_list_id`, `updated_at`, `variant_id` |
          | `default_variant_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `default_variant_tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |
          | `labels_` | `created_at`, `id`, `name`, `updated_at` |
          | `option_types_` | `created_at`, `id`, `kind`, `label`, `name`, `position`, `updated_at` |
          | `product_categories_` | `category_id`, `created_at`, `id`, `position`, `product_id`, `updated_at` |
          | `product_type_` | `created_at`, `id`, `name`, `updated_at` |
          | `product_type_option_types_` | `created_at`, `id`, `kind`, `label`, `name`, `position`, `updated_at` |
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `store_` | `created_at`, `id`, `name`, `updated_at` |
          | `tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `variants_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `variants_option_values_` | `created_at`, `id`, `label`, `name`, `position`, `updated_at` |
          | `variants_prices_` | `amount`, `compare_at_amount`, `created_at`, `currency`, `id`, `min_quantity`, `price_list_id`, `updated_at`, `variant_id` |
          | `variants_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `variants_tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |

          </Accordion>

          **Sort by:** `available_on`, `created_at`, `description`, `discontinue_on`, `id`, `name`, `price`, `seller_id`, `slug`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Product
        sortable:
        - available_on
        - created_at
        - description
        - discontinue_on
        - id
        - name
        - price
        - seller_id
        - slug
        - status
        - updated_at
      responses:
        '200':
          description: products found
          content:
            application/json:
              example:
                data: []
                meta:
                  page: 1
                  limit: 25
                  count: 0
                  pages: 1
                  from: 0
                  to: 0
                  in: 0
                  previous:
                  next:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/Product"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Add products to a collection
      tags:
      - Collections
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Curates products into the collection in bulk (appended to the end). Already-curated products are skipped; the count reports what was added.

        **Required scope:** `write_collections` (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 { added_count } = await client.collections.products.create('coll_UkLWZg9DAJ', [
            'prod_UkLWZg9DAJ',
            'prod_9XbR2kQwLm',
          ])
      - lang: bash
        label: Spree CLI
        source: spree api post /collections/{collection_id}/products -d '{ ... }'
      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: collection_id
        in: path
        required: true
        description: Collection ID
        schema:
          type: string
      responses:
        '201':
          description: products added
          content:
            application/json:
              example:
                added_count: 1
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductMembershipParams"
        required: true
    delete:
      summary: Remove products from a collection
      tags:
      - Collections
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Removes products from the collection's manual curation in bulk. Ids that are not curated are ignored; the count reports what was removed.

        **Required scope:** `write_collections` (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 { removed_count } = await client.collections.products.delete('coll_UkLWZg9DAJ', [
            'prod_UkLWZg9DAJ',
          ])
      - lang: bash
        label: Spree CLI
        source: spree api delete /collections/{collection_id}/products
      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: collection_id
        in: path
        required: true
        description: Collection ID
        schema:
          type: string
      responses:
        '200':
          description: products removed
          content:
            application/json:
              example:
                removed_count: 1
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductMembershipParams"
        required: true
  "/api/v3/admin/collections/{collection_id}/products/{id}/reposition":
    patch:
      summary: Reposition a collection product
      tags:
      - Collections
      operationId: collections_reposition_product
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Moves a product to a new index among the collection's products.

        **Required scope:** `write_collections` (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',
          })

          // Moves the product to the top of the collection; positions are 0-based.
          await client.collections.products.reposition('coll_UkLWZg9DAJ', 'prod_UkLWZg9DAJ', {
            new_position: 0,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /collections/{collection_id}/products/{id}/reposition
          -d '{"new_position":0}'
      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: collection_id
        in: path
        required: true
        description: Collection ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Product ID
        schema:
          type: string
      responses:
        '204':
          description: product repositioned
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductMembershipRepositionParams"
        required: true
  "/api/v3/admin/collection_rules/types":
    get:
      summary: List available collection rule types
      tags:
      - Collections
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Enumerates the registered rule kinds with their labels and descriptions — drives the rule picker on an automatic collection. Plugins extend the list by registering `Spree::CollectionRule` subclasses via `config.spree.collection_rules`. The `type` returned here is the wire shorthand accepted when writing a collection's `rules`.

        **Required scope:** `read_collections` (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.collectionRules.types()
      - lang: bash
        label: Spree CLI
        source: spree api get /collection_rules/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: types found
          content:
            application/json:
              example:
                data:
                - type: sale
                  label: On sale
                  description: Products currently discounted below their compare-at
                    price
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: available_on
                  label: Recently published
                  description: Products published within the last N days
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: tag
                  label: Tag
                  description: Products carrying a matching tag
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
  "/api/v3/admin/commission_lines":
    get:
      summary: List commission lines
      tags:
      - Commission Lines
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        What each sale actually earned the marketplace, frozen when the order
        was placed. A later change to a commission rate never reaches these.

        `amount` is the fee charged to the seller and `tax_amount` is the VAT on
        that fee — the marketplace's own service to the seller, a supply
        separate from the sale itself, which is why the two are not folded
        together. `total` is their sum.

        One line per commissioned item, plus one per delivery when the rate that
        applied charges shipping too — read `line_item_id` and `fulfillment_id`
        to tell them apart.

        Read-only: correcting a charge is a reversal, not an edit.


        **Required scope:** `read_commissions` (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',
          })

          // `amount` is the fee and `tax_amount` is the VAT charged on that fee — two
          // separate supplies, which is why they are not folded together.
          const { data: commissionLines } = await client.commissionLines.list({ page: 1, limit: 25 })
      - lang: bash
        label: Spree CLI
        source: spree api get /commission_lines -d '{"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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: sort
        in: query
        required: false
        description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`).
        schema:
          type: string
      - name: expand
        in: query
        required: false
        description: Comma-separated associations to embed (e.g., `commission_rate`).
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[amount_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `amount` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `currency` | One of the `CurrencyCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `kind` | One of `percentage`, `fixed` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `order_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `rate` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `tax_amount` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `total` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[commission_rate_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `commission_rate_` | `code`, `created_at`, `enabled`, `id`, `include_shipping`, `kind`, `name`, `position`, `tax_inclusive`, `updated_at`, `value` |
          | `commission_rate_commission_rules_` | `created_at`, `id`, `updated_at` |
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |

          </Accordion>

          **Sort by:** `amount`, `created_at`, `currency`, `id`, `kind`, `order_id`, `rate`, `tax_amount`, `total`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CommissionLine
        sortable:
        - amount
        - created_at
        - currency
        - id
        - kind
        - order_id
        - rate
        - tax_amount
        - total
        - updated_at
      responses:
        '200':
          description: commission lines found
          content:
            application/json:
              example:
                data:
                - id: cline_UkLWZg9DAJ
                  kind: percentage
                  currency: USD
                  taxability_reason:
                  country_code:
                  state_code:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  rate: '10'
                  tax_rate: '0'
                  amount: '10.00'
                  tax_amount: '2.10'
                  total: '12.10'
                  order_id: or_UkLWZg9DAJ
                  seller_id: sel_UkLWZg9DAJ
                  line_item_id: li_UkLWZg9DAJ
                  fulfillment_id:
                  commission_rate_id:
                  seller_name: Sparks Audio
                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/CommissionLine"
                  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/commission_lines/{id}":
    parameters:
    - name: id
      in: path
      description: Commission line ID
      required: true
      schema:
        type: string
    get:
      summary: Get a commission line
      tags:
      - Commission Lines
      security:
      - api_key: []
        bearer_auth: []
      description: "**Required scope:** `read_commissions` (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 commissionLine = await client.commissionLines.get('cline_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /commission_lines/{id}
      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: commission line found
          content:
            application/json:
              example:
                id: cline_UkLWZg9DAJ
                kind: percentage
                currency: USD
                taxability_reason:
                country_code:
                state_code:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                rate: '10'
                tax_rate: '0'
                amount: '10.00'
                tax_amount: '2.10'
                total: '12.10'
                order_id: or_UkLWZg9DAJ
                seller_id: sel_UkLWZg9DAJ
                line_item_id: li_UkLWZg9DAJ
                fulfillment_id:
                commission_rate_id:
                seller_name: Sparks Audio
              schema:
                "$ref": "#/components/schemas/CommissionLine"
        '404':
          description: commission line not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Commission line not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/commission_rates":
    get:
      summary: List commission rates
      tags:
      - Commission Rates
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        What the marketplace charges its sellers.

        Rates are returned in resolution order: the list is walked top-down and
        the first rate whose targeting matches the sale wins, so the order you
        see is the precedence. Move a rate with `position` on update.

        A rate carrying no rules matches every sale — `global` says so — which
        is how a marketplace expresses a single default. Because resolution
        stops at the first match, a global rate makes everything below it
        unreachable, so it belongs at the bottom.


        **Required scope:** `read_commissions` (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',
          })

          // Rates come back with their targeting attached. A rate holding no rules
          // applies to every sale.
          const { data: commissionRates } = await client.commissionRates.list({ page: 1, limit: 25 })
      - lang: bash
        label: Spree CLI
        source: spree api get /commission_rates -d '{"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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: sort
        in: query
        required: false
        description: Sort by field. Prefix with `-` for descending (e.g., `-position`).
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `enabled` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `include_shipping` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `kind` | One of `percentage`, `fixed` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `tax_inclusive` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `value` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[commission_rules_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `commission_rules_` | `created_at`, `id`, `updated_at` |

          </Accordion>

          **Sort by:** `code`, `created_at`, `enabled`, `id`, `include_shipping`, `kind`, `name`, `position`, `tax_inclusive`, `updated_at`, `value`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CommissionRate
        sortable:
        - code
        - created_at
        - enabled
        - id
        - include_shipping
        - kind
        - name
        - position
        - tax_inclusive
        - updated_at
        - value
      responses:
        '200':
          description: commission rates found
          content:
            application/json:
              example:
                data:
                - id: crate_UkLWZg9DAJ
                  name: Standard
                  code:
                  enabled: true
                  position: 1
                  kind: percentage
                  tax_inclusive: false
                  include_shipping: false
                  metadata: {}
                  deleted_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  value: '10'
                  commission_tax_rate:
                  amounts: {}
                  bounds: {}
                  global: true
                  rules: []
                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/CommissionRate"
                  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 commission rate
      tags:
      - Commission Rates
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Sets what the marketplace charges, and which sales it applies to.

        `rules` is the rate's whole targeting, sent inline. Every rule has to
        hold, and a rule naming several records means any of them — so
        "(Cameras OR Audio) AND that seller" is a category rule holding two ids
        beside a seller rule holding one. Send no rules to charge every sale.

        Rule kinds come from `GET /commission_rates/rule_types`, which also
        describes the configuration each one takes. A marketplace that adds its
        own kind sees it there without this endpoint changing.

        `commission_tax_rate` is VAT on the commission itself — the
        marketplace's own service to the seller, a separate supply from the
        sale. Leave it null to let the store's tax engine answer for wherever
        the seller's business sits.


        **Required scope:** `write_commissions` (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',
          })

          // Charges this seller 12.5% of every sale, with VAT on the commission itself
          // left to your tax settings. The rate lands at the top of the list, so it
          // resolves ahead of anything more general already there.
          const commissionRate = await client.commissionRates.create({
            name: 'Audio sellers',
            kind: 'percentage',
            value: '12.5',
            rules: [{ type: 'seller_rule', preferences: { seller_ids: ['sel_a1b2c3'] } }],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /commission_rates -d '{"name":"Audio sellers","kind":"percentage","value":"12.5","rules":[{"type":"seller_rule","preferences":{"seller_ids":["sel_a1b2c3"]}}]}'
      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: commission rate created
          content:
            application/json:
              example:
                id: crate_gbHJdmfrXB
                name: Audio sellers
                code:
                enabled: true
                position: 1
                kind: percentage
                tax_inclusive: false
                include_shipping: false
                metadata: {}
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                value: '12.5'
                commission_tax_rate:
                amounts: {}
                bounds: {}
                global: true
                rules: []
              schema:
                "$ref": "#/components/schemas/CommissionRate"
        '422':
          description: validation failed
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: needs a flat fee amount in at least one currency
                  details:
                    base:
                    - code: commission_rate_needs_an_amount
                      message: needs a flat fee amount in at least one currency
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CommissionRateCreateParams"
        required: true
  "/api/v3/admin/commission_rates/rule_types":
    get:
      summary: List the commission rule kinds
      tags:
      - Commission Rates
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Every rule kind a rate can be narrowed by, with the schema describing
        the configuration it takes — so a client builds its editor from what
        this marketplace has rather than a list hardcoded to match core's.

        `association_fields` names any catalog-scale reference a kind keeps
        outside its preferences, so an editor knows to render a picker for it.


        **Required scope:** `read_commissions` (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',
          })

          // Each kind comes with the JSON Schema of its configuration.
          const { data: ruleTypes } = await client.commissionRates.ruleTypes()
      - lang: bash
        label: Spree CLI
        source: spree api get /commission_rates/rule_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: subject types found
          content:
            application/json:
              example:
                data:
                - type: seller_rule
                  name: Seller
                  description: Charges this rate only when the seller is one of the
                    selected
                  schema:
                    type: object
                    properties:
                      seller_ids:
                        type: array
                        items:
                          type: string
                          format: prefixed-id
                          pattern: "^sel_[A-Za-z0-9]+$"
                          x-spree-prefix: sel
                        default: []
                    additionalProperties: false
                  association_fields:
                  - seller_ids
                - type: category_rule
                  name: Category
                  description: Charges this rate only for products in the selected
                    categories, and anything filed beneath them
                  schema:
                    type: object
                    properties:
                      category_ids:
                        type: array
                        items:
                          type: string
                          format: prefixed-id
                          pattern: "^ctg_[A-Za-z0-9]+$"
                          x-spree-prefix: ctg
                        default: []
                    additionalProperties: false
                  association_fields:
                  - category_ids
                - type: product_rule
                  name: Product
                  description: Charges this rate only for the selected products
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                  association_fields:
                  - product_ids
                - type: item_total_rule
                  name: Sale value
                  description: Charges this rate only on sales within a value range
                  schema:
                    type: object
                    properties:
                      min_amount:
                        type:
                        - string
                        - 'null'
                        format: money
                        pattern: "^-?\\d+(\\.\\d+)?$"
                      max_amount:
                        type:
                        - string
                        - 'null'
                        format: money
                        pattern: "^-?\\d+(\\.\\d+)?$"
                    additionalProperties: false
                  association_fields: []
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        type:
                          type: string
                          example: seller_rule
                        name:
                          type: string
                          example: Seller
                        description:
                          type: string
                          nullable: true
                        schema:
                          type: object
                          description: JSON Schema of the type's `preferences`
                        association_fields:
                          type: array
                          items:
                            type: string
  "/api/v3/admin/commission_rates/{id}":
    parameters:
    - name: id
      in: path
      description: Commission rate ID
      required: true
      schema:
        type: string
    get:
      summary: Get a commission rate
      tags:
      - Commission Rates
      security:
      - api_key: []
        bearer_auth: []
      description: "**Required scope:** `read_commissions` (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 commissionRate = await client.commissionRates.get('crate_a1b2c3')
      - lang: bash
        label: Spree CLI
        source: spree api get /commission_rates/{id}
      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: commission rate found
          content:
            application/json:
              example:
                id: crate_UkLWZg9DAJ
                name: Standard
                code:
                enabled: true
                position: 1
                kind: percentage
                tax_inclusive: false
                include_shipping: false
                metadata: {}
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                value: '10'
                commission_tax_rate:
                amounts: {}
                bounds: {}
                global: true
                rules: []
              schema:
                "$ref": "#/components/schemas/CommissionRate"
        '404':
          description: commission rate not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Commission rate not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update a commission rate
      tags:
      - Commission Rates
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Editing a rate changes what the next sale is charged, never what a past
        one was: commission lines keep their own snapshot of the rate that
        applied.


        **Required scope:** `write_commissions` (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',
          })

          // `rules` is the rate's whole targeting — what you send replaces what it holds.
          // `position` moves the rate: 1 is tried first, and the first match wins.
          //
          // Every rule has to hold, so this charges 15% only on camera sales worth 50 or
          // more. Call ruleTypes() for the kinds this marketplace has.
          const commissionRate = await client.commissionRates.update('crate_a1b2c3', {
            value: '15',
            position: 1,
            rules: [
              { type: 'category_rule', preferences: { category_ids: ['ctg_d4e5f6'] } },
              { type: 'item_total_rule', preferences: { min_amount: '50' } },
            ],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /commission_rates/{id} -d '{"value":"15","position":1,"rules":[{"type":"category_rule","preferences":{"category_ids":["ctg_d4e5f6"]}},{"type":"item_total_rule","preferences":{"min_amount":"50"}}]}'
      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: commission rate updated
          content:
            application/json:
              example:
                id: crate_UkLWZg9DAJ
                name: Standard
                code:
                enabled: true
                position: 1
                kind: percentage
                tax_inclusive: false
                include_shipping: false
                metadata: {}
                deleted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                value: '15'
                commission_tax_rate:
                amounts: {}
                bounds: {}
                global: true
                rules: []
              schema:
                "$ref": "#/components/schemas/CommissionRate"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CommissionRateUpdateParams"
        required: true
    delete:
      summary: Delete a commission rate
      tags:
      - Commission Rates
      security:
      - api_key: []
        bearer_auth: []
      description: "**Required scope:** `write_commissions` (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',
          })

          // Commission already charged is unaffected — the lines keep their own snapshot.
          await client.commissionRates.delete('crate_a1b2c3')
      - lang: bash
        label: Spree CLI
        source: spree api delete /commission_rates/{id}
      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: commission rate deleted
  "/api/v3/admin/companies/{company_id}/addresses":
    get:
      summary: List company addresses
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the business's addresses: its sites, billing address and delivery points.

        **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.companies.addresses.list('comp_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /companies/{company_id}/addresses
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: company_id
        in: path
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[address1_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `address1` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `address2` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `city` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `company` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `country_code` | One of the `CountryCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `first_name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `last_name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `phone` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `postal_code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `state_code` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Address
        sortable:
        - address1
        - address2
        - city
        - company
        - country_code
        - created_at
        - first_name
        - id
        - last_name
        - phone
        - postal_code
        - state_code
        - updated_at
      responses:
        '200':
          description: addresses found
          content:
            application/json:
              example:
                data:
                - id: addr_UkLWZg9DAJ
                  label: Head office
                  first_name:
                  last_name:
                  full_name: ''
                  address1: 25 Lovely Street
                  address2: Northwest
                  postal_code: '10118'
                  city: New York
                  phone: 555-555-0199
                  company: Company
                  country_name: United States
                  country_code: US
                  state_text: NY
                  state_code: NY
                  quick_checkout: false
                  is_default_billing: false
                  is_default_shipping: false
                  state_name: New York
                  owner:
                    id: comp_UkLWZg9DAJ
                    type: company
                    name: Acme Corp 3
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  latitude:
                  longitude:
                  customer_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/Address"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Create a company address
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds an address to the business. Pass `default_billing: true` or `default_shipping: true` to make it the default of that kind.

        **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.companies.addresses.create('comp_UkLWZg9DAJ', {
            first_name: 'Jane',
            last_name: 'Doe',
            company: 'Acme Wholesale',
            label: 'Warehouse',
            address1: '350 Fifth Avenue',
            city: 'New York',
            postal_code: '10118',
            country_code: 'US',
            state_code: 'NY',
            phone: '+12125551234',
            default_shipping: true,
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /companies/{company_id}/addresses -d '{"first_name":"Jane","last_name":"Doe","company":"Acme
          Wholesale","label":"Warehouse","address1":"350 Fifth Avenue","city":"New
          York","postal_code":"10118","country_code":"US","state_code":"NY","phone":"+12125551234","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: company_id
        in: path
        required: true
        schema:
          type: string
      responses:
        '201':
          description: address created
          content:
            application/json:
              example:
                id: addr_gbHJdmfrXB
                label: Warehouse
                first_name:
                last_name:
                full_name: ''
                address1: 350 Fifth Avenue
                address2:
                postal_code: '10118'
                city: New York
                phone: "+12125551234"
                company: Acme Wholesale
                country_name: United States
                country_code: US
                state_text: NY
                state_code: NY
                quick_checkout: false
                is_default_billing: false
                is_default_shipping: true
                state_name: New York
                owner:
                  id: comp_UkLWZg9DAJ
                  type: company
                  name: Acme Corp 4
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                latitude:
                longitude:
                customer_id:
              schema:
                "$ref": "#/components/schemas/Address"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CompanyAddressCreateParams"
        required: true
  "/api/v3/admin/companies/{company_id}/addresses/{id}":
    patch:
      summary: Update a company address
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Changes an address of the business. Pass `default_billing` or `default_shipping` to move that default to it, or `false` to give it up.

        **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.companies.addresses.update('comp_UkLWZg9DAJ', 'addr_k5nR8xLqPz', {
            label: 'Northern Warehouse',
            default_billing: true,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /companies/{company_id}/addresses/{id} -d '{"label":"Northern
          Warehouse","default_billing":true}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: company_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
                label: Northern Warehouse
                first_name:
                last_name:
                full_name: ''
                address1: 27 Lovely Street
                address2: Northwest
                postal_code: '10118'
                city: New York
                phone: 555-555-0199
                company: Company
                country_name: United States
                country_code: US
                state_text: NY
                state_code: NY
                quick_checkout: false
                is_default_billing: true
                is_default_shipping: false
                state_name: New York
                owner:
                  id: comp_UkLWZg9DAJ
                  type: company
                  name: Acme Corp 5
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                latitude:
                longitude:
                customer_id:
              schema:
                "$ref": "#/components/schemas/Address"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CompanyAddressUpdateParams"
        required: true
  "/api/v3/admin/companies/{company_id}/invitations":
    get:
      summary: List company invitations
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the invitations into this business that are still waiting to be accepted.

        **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: invitations } = await client.companies.invitations.list('comp_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /companies/{company_id}/invitations
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: company_id
        in: path
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[email_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `email` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `email`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CompanyInvitation
        sortable:
        - created_at
        - email
        - id
        - updated_at
      responses:
        '200':
          description: invitations found
          content:
            application/json:
              example:
                data:
                - id: cinv_UkLWZg9DAJ
                  email: buyer@example.com
                  expires_at: '2026-02-14T12:00:00.000Z'
                  company_id: comp_UkLWZg9DAJ
                  status: pending
                  accepted_at:
                  revoked_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                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/CompanyInvitation"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/companies/{company_id}/memberships":
    parameters:
    - name: x-spree-api-key
      in: header
      required: true
      schema:
        type: string
    - name: Authorization
      in: header
      required: true
      schema:
        type: string
    - name: company_id
      in: path
      required: true
      schema:
        type: string
    get:
      summary: List company members
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the people with standing over this node. Standing covers the node and everything below it in the tree.

        **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: members } = await client.companies.memberships.list('comp_86Rf07xd4z')
      - lang: bash
        label: Spree CLI
        source: spree api get /companies/{company_id}/memberships
      parameters:
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CompanyMembership
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: members found
          content:
            application/json:
              example:
                data:
                - id: cmem_UkLWZg9DAJ
                  company_id: comp_UkLWZg9DAJ
                  customer_id: cust_UkLWZg9DAJ
                  email: ezequiel.monahan@heller.ca
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Add a member
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds a person to the node, either an existing customer by `customer_id` or anyone by
        `customer_email`. A customer, or an email matching one, becomes a membership immediately
        (a `cmem_…` id); an unknown email becomes an invitation (a `cinv_…` id) and the invite
        email goes out.


        **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',
          })

          // An existing customer becomes a member immediately; an unknown email
          // becomes an invitation (check the returned id prefix: cmem_ vs cinv_).
          const member = await client.companies.memberships.create('comp_86Rf07xd4z', {
            customer_email: 'buyer@example.com',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /companies/{company_id}/memberships -d '{"customer_email":"buyer@example.com"}'
      parameters: []
      responses:
        '201':
          description: member added
          content:
            application/json:
              example:
                id: cmem_UkLWZg9DAJ
                company_id: comp_UkLWZg9DAJ
                customer_id: cust_UkLWZg9DAJ
                email: buyer@example.com
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CompanyMembershipCreateParams"
        required: true
  "/api/v3/admin/companies/{company_id}/tax_exemption_certificates":
    parameters:
    - name: x-spree-api-key
      in: header
      required: true
      schema:
        type: string
    - name: Authorization
      in: header
      required: true
      schema:
        type: string
    - name: company_id
      in: path
      required: true
      schema:
        type: string
    get:
      summary: List tax exemption certificates
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a business's exemption evidence. `active` is the field that decides whether a certificate
        exempts a sale: a verified certificate stops counting once its expiry date passes, so the status
        alone does not answer it.


        **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: certificates } =
            await client.companies.taxExemptionCertificates.list('comp_UkLWZg9DAJ')

          // `active` — not `status` — answers whether one exempts a sale: a verified
          // certificate stops counting once its expiry date passes.
          const applying = certificates.filter((certificate) => certificate.active)
      - lang: bash
        label: Spree CLI
        source: spree api get /companies/{company_id}/tax_exemption_certificates
      parameters:
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[certificate_number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `certificate_number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `expires_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `status` | One of `pending`, `verified`, `expired`, `revoked` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `tax_exemption_reason_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `certificate_number`, `created_at`, `expires_at`, `id`, `status`, `tax_exemption_reason_id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: TaxExemptionCertificate
        sortable:
        - certificate_number
        - created_at
        - expires_at
        - id
        - status
        - tax_exemption_reason_id
        - updated_at
      responses:
        '200':
          description: certificates found
          content:
            application/json:
              example:
                data:
                - id: cert_UkLWZg9DAJ
                  certificate_number: DE-RESALE-1
                  status: pending
                  issuing_authority:
                  metadata: {}
                  issued_at:
                  expires_at:
                  verified_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  company_id: comp_UkLWZg9DAJ
                  tax_exemption_reason_id: txr_UkLWZg9DAJ
                  country_code:
                  state_code:
                  active: false
                  lapsed: false
                  can_be_deleted: true
                  document_filename:
                  document_byte_size:
                  document_url:
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Create a tax exemption certificate
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Records exemption evidence against a business. Certificates start `pending` and exempt nothing
        until verified.

        `country_code` and `state_code` say where the certificate holds — omit both for one valid
        everywhere, give only the country for one valid throughout it. `document_signed_id` takes the
        `signed_id` returned by `POST /api/v3/admin/files`.


        **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',
          })

          // `signed_id` comes from `client.files.upload(file, { visibility: 'private' })`.
          const certificate = await client.companies.taxExemptionCertificates.create('comp_UkLWZg9DAJ', {
            certificate_number: 'DE-RESALE-7',
            tax_exemption_reason_id: 'txr_UkLWZg9DAJ',
            country_code: 'DE',
            document_signed_id: signed_id,
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /companies/{company_id}/tax_exemption_certificates
          -d '{ ... }'
      parameters: []
      responses:
        '201':
          description: certificate created
          content:
            application/json:
              example:
                id: cert_gbHJdmfrXB
                certificate_number: DE-RESALE-7
                status: pending
                issuing_authority:
                metadata: {}
                issued_at:
                expires_at:
                verified_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                company_id: comp_UkLWZg9DAJ
                tax_exemption_reason_id: txr_UkLWZg9DAJ
                country_code: DE
                state_code:
                active: false
                lapsed: false
                can_be_deleted: true
                document_filename: resale.pdf
                document_byte_size: 20
                document_url: "/api/v3/admin/companies/comp_UkLWZg9DAJ/tax_exemption_certificates/cert_gbHJdmfrXB/download"
        '422':
          description: invalid request
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Certificate number can't be blank
                  details:
                    certificate_number:
                    - code: blank
                      message: can't be blank
                      specific: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaxExemptionCertificateCreateParams"
        required: true
  "/api/v3/admin/companies/{company_id}/tax_exemption_certificates/{id}":
    parameters:
    - name: x-spree-api-key
      in: header
      required: true
      schema:
        type: string
    - name: Authorization
      in: header
      required: true
      schema:
        type: string
    - name: company_id
      in: path
      required: true
      schema:
        type: string
    - name: id
      in: path
      required: true
      schema:
        type: string
    patch:
      summary: Update a tax exemption certificate
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Corrects the details recorded for a certificate, such as its issuing authority or expiry date.

        **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 certificate = await client.companies.taxExemptionCertificates.update(
            'comp_UkLWZg9DAJ',
            'cert_k5nR8xLqPz',
            { issuing_authority: 'Finanzamt Berlin', expires_at: '2027-12-31T23:59:59Z' },
          )
      - lang: bash
        label: Spree CLI
        source: spree api patch /companies/{company_id}/tax_exemption_certificates/{id}
          -d '{"issuing_authority":"Finanzamt Berlin","expires_at":"2027-12-31T23:59:59Z"}'
      parameters: []
      responses:
        '200':
          description: certificate updated
          content:
            application/json:
              example:
                id: cert_UkLWZg9DAJ
                certificate_number: DE-RESALE-1
                status: pending
                issuing_authority: Finanzamt Berlin
                metadata: {}
                issued_at:
                expires_at: '2027-12-31T23:59:59.000Z'
                verified_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                company_id: comp_UkLWZg9DAJ
                tax_exemption_reason_id: txr_UkLWZg9DAJ
                country_code:
                state_code:
                active: false
                lapsed: false
                can_be_deleted: true
                document_filename:
                document_byte_size:
                document_url:
              schema:
                "$ref": "#/components/schemas/TaxExemptionCertificate"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaxExemptionCertificateUpdateParams"
        required: true
  "/api/v3/admin/companies/{company_id}/tax_exemption_certificates/{id}/verify":
    parameters:
    - name: x-spree-api-key
      in: header
      required: true
      schema:
        type: string
    - name: Authorization
      in: header
      required: true
      schema:
        type: string
    - name: company_id
      in: path
      required: true
      schema:
        type: string
    - name: id
      in: path
      required: true
      schema:
        type: string
    patch:
      summary: Verify a tax exemption certificate
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Accepts the certificate as evidence, which is what makes it exempt sales. Only a pending
        certificate can be accepted — re-accepting a revoked one would restore evidence that was
        deliberately withdrawn. An installation that checks numbers against a registry, or requires a
        second approval, can refuse here, and the refusal is returned as a validation error.


        **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',
          })

          // Accepting is what makes a certificate exempt sales. Only a pending one can
          // be accepted, and an installation's own checks can refuse here.
          const certificate = await client.companies.taxExemptionCertificates.verify(
            'comp_UkLWZg9DAJ',
            'cert_UkLWZg9DAJ',
          )
      - lang: bash
        label: Spree CLI
        source: spree api patch /companies/{company_id}/tax_exemption_certificates/{id}/verify
          -d '{ ... }'
      responses:
        '200':
          description: certificate verified
          content:
            application/json:
              example:
                id: cert_UkLWZg9DAJ
                certificate_number: DE-RESALE-1
                status: verified
                issuing_authority:
                metadata: {}
                issued_at:
                expires_at:
                verified_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                company_id: comp_UkLWZg9DAJ
                tax_exemption_reason_id: txr_UkLWZg9DAJ
                country_code:
                state_code:
                active: true
                lapsed: false
                can_be_deleted: false
                document_filename:
                document_byte_size:
                document_url:
  "/api/v3/admin/companies/{company_id}/tax_exemption_certificates/{id}/revoke":
    parameters:
    - name: x-spree-api-key
      in: header
      required: true
      schema:
        type: string
    - name: Authorization
      in: header
      required: true
      schema:
        type: string
    - name: company_id
      in: path
      required: true
      schema:
        type: string
    - name: id
      in: path
      required: true
      schema:
        type: string
    patch:
      summary: Revoke a tax exemption certificate
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Withdraws accepted evidence. A verified certificate cannot be deleted — how a sale was taxed has to remain explainable — so revoking is the way out.

        **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',
          })

          // A verified certificate cannot be deleted — how a sale was taxed has to stay
          // explainable — so revoking is the way out.
          const certificate = await client.companies.taxExemptionCertificates.revoke(
            'comp_UkLWZg9DAJ',
            'cert_UkLWZg9DAJ',
          )
      - lang: bash
        label: Spree CLI
        source: spree api patch /companies/{company_id}/tax_exemption_certificates/{id}/revoke
          -d '{ ... }'
      responses:
        '200':
          description: certificate revoked
          content:
            application/json:
              example:
                id: cert_gbHJdmfrXB
                certificate_number: CERT-1
                status: revoked
                issuing_authority:
                metadata: {}
                issued_at:
                expires_at:
                verified_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                company_id: comp_UkLWZg9DAJ
                tax_exemption_reason_id: txr_UkLWZg9DAJ
                country_code:
                state_code:
                active: false
                lapsed: false
                can_be_deleted: true
                document_filename:
                document_byte_size:
                document_url:
  "/api/v3/admin/companies/{company_id}/tax_exemption_certificates/{id}/download":
    parameters:
    - name: x-spree-api-key
      in: header
      required: true
      schema:
        type: string
    - name: Authorization
      in: header
      required: true
      schema:
        type: string
    - name: company_id
      in: path
      required: true
      schema:
        type: string
    - name: id
      in: path
      required: true
      schema:
        type: string
    get:
      summary: Download a certificate document
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Streams the uploaded document. Deliberately not a storage link: the bytes come through the API so
        the same credentials apply to every read of a confidential document. Requires only read access.


        **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',
          })

          // The document is served through the API, so fetch it with the API key,
          // then drive the browser download from a Blob.
          const certificate = await client.companies.taxExemptionCertificates.get(
            'comp_UkLWZg9DAJ',
            'cert_k5nR8xLqPz',
          )

          if (certificate.document_url) {
            const response = await fetch(`https://your-store.com${certificate.document_url}`, {
              headers: { 'X-Spree-API-Key': 'sk_xxx' },
            })
            if (!response.ok) throw new Error(`Download failed: ${response.status}`)

            const url = URL.createObjectURL(await response.blob())
            const link = Object.assign(document.createElement('a'), {
              href: url,
              download: certificate.document_filename ?? 'certificate',
            })
            link.click()
            URL.revokeObjectURL(url)
          }
      - lang: bash
        label: Spree CLI
        source: spree api get /companies/{company_id}/tax_exemption_certificates/{id}/download
      responses:
        '200':
          description: document streamed
        '422':
          description: no document attached
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Certificate has no attached document
  "/api/v3/admin/companies/{company_id}/tax_identifiers":
    parameters:
    - name: x-spree-api-key
      in: header
      required: true
      schema:
        type: string
    - name: Authorization
      in: header
      required: true
      schema:
        type: string
    - name: company_id
      in: path
      required: true
      schema:
        type: string
    get:
      summary: List company tax registrations
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the business's tax registrations, one per kind. A business registration takes precedence
        over the buyer's own when a sale is for that business, because the invoice is addressed to the
        entity rather than the person who placed the order.


        **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: registrations } = await client.companies.taxIdentifiers.list('comp_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /companies/{company_id}/tax_identifiers
      parameters:
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: TaxIdentifier
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: registrations found
          content:
            application/json:
              example:
                data:
                - id: txi_UkLWZg9DAJ
                  kind: eu_vat
                  value: DE100000008
                  validation_status:
                  validation_evidence:
                  source:
                  validated_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  validatable: false
                  customer_id:
                  cart_id:
                  order_id:
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Create a company tax registration
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Registers a tax number against the business. Verification against the relevant registry runs in
        the background where a validator is installed for the kind; a stock installation registers none,
        leaving the status unattempted.


        **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',
          })

          // A business registration outranks the buyer's own when the sale is for that business.
          const registration = await client.companies.taxIdentifiers.create('comp_UkLWZg9DAJ', {
            kind: 'eu_vat',
            value: 'DE123456789',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /companies/{company_id}/tax_identifiers -d '{"kind":"eu_vat","value":"DE123456789"}'
      parameters: []
      responses:
        '201':
          description: registration created
          content:
            application/json:
              example:
                id: txi_gbHJdmfrXB
                kind: gb_vat
                value: GB123456789
                validation_status:
                validation_evidence:
                source:
                validated_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                validatable: false
                customer_id:
                cart_id:
                order_id:
        '422':
          description: invalid request
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Registration type has already been taken
                  details:
                    kind:
                    - value: eu_vat
                      code: taken
                      message: has already been taken
                      specific: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/TaxIdentifierCreateParams"
        required: true
  "/api/v3/admin/companies/{company_id}/tax_identifiers/{id}/validate":
    parameters:
    - name: x-spree-api-key
      in: header
      required: true
      schema:
        type: string
    - name: Authorization
      in: header
      required: true
      schema:
        type: string
    - name: company_id
      in: path
      required: true
      schema:
        type: string
    - name: id
      in: path
      required: true
      schema:
        type: string
    post:
      summary: Re-check a company tax registration
      tags:
      - Companies
      operationId: company_tax_identifiers_validate
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Asks the registry again. Manual because a registry answers only "valid now" — a number verified
        last year may have been deregistered since — and because a check that came back unavailable
        cannot otherwise be retried without editing the number.


        **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',
          })

          // A registry answers only "valid now", so a number verified last year may
          // have been deregistered since. The check is queued; poll for the verdict.
          const registration = await client.companies.taxIdentifiers.validate(
            'comp_UkLWZg9DAJ',
            'txi_UkLWZg9DAJ',
          )
      - lang: bash
        label: Spree CLI
        source: spree api post /companies/{company_id}/tax_identifiers/{id}/validate
          -d '{ ... }'
      responses:
        '422':
          description: no validator installed for this kind
          content:
            application/json:
              example:
                error:
                  code: tax_id_not_validatable
                  message: No registry validator is installed for tax identifier kind
                    'eu_vat'
  "/api/v3/admin/companies":
    get:
      summary: List companies
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the business customers of the current store.

        **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: companies } = await client.companies.list({ search: 'Acme' })
      - lang: bash
        label: Spree CLI
        source: spree api get /companies -d '{"search":"Acme"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `kind` | One of `company`, `division` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `parent_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `po_number_required` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[children_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `children_` | `created_at`, `id`, `kind`, `name`, `parent_id`, `po_number_required`, `updated_at` |
          | `children_external_references_` | `created_at`, `external_id`, `id`, `resource_type`, `system`, `updated_at` |
          | `children_memberships_` | `created_at`, `id`, `updated_at` |
          | `external_references_` | `created_at`, `external_id`, `id`, `resource_type`, `system`, `updated_at` |
          | `memberships_` | `created_at`, `id`, `updated_at` |
          | `parent_` | `created_at`, `id`, `kind`, `name`, `parent_id`, `po_number_required`, `updated_at` |
          | `parent_external_references_` | `created_at`, `external_id`, `id`, `resource_type`, `system`, `updated_at` |
          | `parent_memberships_` | `created_at`, `id`, `updated_at` |

          </Accordion>

          **Sort by:** `created_at`, `id`, `kind`, `name`, `parent_id`, `po_number_required`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Company
        sortable:
        - created_at
        - id
        - kind
        - name
        - parent_id
        - po_number_required
        - updated_at
      responses:
        '200':
          description: companies found
          content:
            application/json:
              example:
                data:
                - id: comp_UkLWZg9DAJ
                  name: Acme Industrial
                  kind: company
                  po_number_required: false
                  parent_id:
                  ancestors: []
                  external_references:
                    erp: ACME-1
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  children_count: 0
                  members_count: 0
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Create a company
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Creates a company node. A root node is a legal entity; pass parent_id and kind to build the organization tree. Exemption certificates and tax registrations hang off legal-entity nodes.

        **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 company = await client.companies.create({
            name: 'Globex Corporation',
            external_references: { erp: 'GLBX-42' },
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /companies -d '{"name":"Globex Corporation","external_references":{"erp":"GLBX-42"}}'
      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: company created
          content:
            application/json:
              example:
                id: comp_gbHJdmfrXB
                name: Globex Corporation
                kind: company
                po_number_required: false
                parent_id:
                ancestors: []
                external_references:
                  erp: GLBX-42
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                children_count: 0
                members_count: 0
        '422':
          description: invalid request
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CompanyCreateParams"
        required: true
  "/api/v3/admin/companies/{id}":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
    patch:
      summary: Update a company
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Updates a company node. Only the attributes sent change.

        **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 company = await client.companies.update('comp_UkLWZg9DAJ', {
            name: 'Acme Industrial Group',
            po_number_required: true,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /companies/{id} -d '{"name":"Acme Industrial Group","po_number_required":true}'
      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: company updated
          content:
            application/json:
              example:
                id: comp_UkLWZg9DAJ
                name: Acme Industrial Group
                kind: company
                po_number_required: true
                parent_id:
                ancestors: []
                external_references:
                  erp: ACME-1
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                children_count: 0
                members_count: 0
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/CompanyUpdateParams"
        required: true
  "/api/v3/admin/custom_field_definitions/resource_types":
    get:
      summary: List what custom fields can be attached to
      tags:
      - Custom Field Definitions
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The resources a definition can describe, from the server's own
        registry (`Spree.custom_fields.enabled_resources`).

        Read this rather than carrying a list: a resource an extension
        registers appears here without a client release, and a `resource_type`
        that is not listed is refused on create.

        `resource_type` is the value to send; `name` is what a merchant calls
        it — send the value back verbatim rather than deriving it from the name.


        **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',
          })

          // What a definition can be attached to. Comes from the server's registry, so
          // a resource an extension adds shows up here without a client release.
          const { data: resourceTypes } = await client.customFieldDefinitions.resourceTypes()
      - lang: bash
        label: Spree CLI
        source: spree api get /custom_field_definitions/resource_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: resource types found
          content:
            application/json:
              example:
                data:
                - resource_type: address
                  name: Addresses
                - resource_type: category
                  name: Categories
                - resource_type: claim
                  name: Claims
                - resource_type: collection
                  name: Collections
                - resource_type: company
                  name: Companies
                - resource_type: credit_card
                  name: Credit Cards
                - resource_type: customer
                  name: Customers
                - resource_type: delivery_method
                  name: Delivery Methods
                - resource_type: exchange
                  name: Exchanges
                - resource_type: fulfillment
                  name: Fulfillments
                - resource_type: gift_card
                  name: Gift Cards
                - resource_type: line_item
                  name: Line Items
                - resource_type: media
                  name: Media
                - resource_type: newsletter_subscriber
                  name: Newsletter Subscribers
                - resource_type: option_type
                  name: Option Types
                - resource_type: option_value
                  name: Option Values
                - resource_type: order
                  name: Orders
                - resource_type: payment_method
                  name: Payment Methods
                - resource_type: payment_source
                  name: Payment Sources
                - resource_type: payment
                  name: Payments
                - resource_type: product_type
                  name: Product Types
                - resource_type: product
                  name: Products
                - resource_type: promotion
                  name: Promotions
                - resource_type: purchase_order
                  name: Purchase Orders
                - resource_type: refund
                  name: Refunds
                - resource_type: return
                  name: Returns
                - resource_type: seller
                  name: Sellers
                - resource_type: stock_level
                  name: Stock Levels
                - resource_type: stock_transfer
                  name: Stock Transfers
                - resource_type: store_credit
                  name: Store Credits
                - resource_type: store
                  name: Stores
                - resource_type: tax_rate
                  name: Tax Rates
                - resource_type: variant
                  name: Variants
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        resource_type:
                          type: string
                          example: seller
                        name:
                          type: string
                          example: Sellers
  "/api/v3/admin/collections/{collection_id}/custom_fields":
    get:
      summary: List collection custom fields
      tags:
      - Collections
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the collection's custom field values.

        **Required scope:** `read_collections` (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.collections.customFields.list('coll_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /collections/{collection_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: collection_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/sellers/{seller_id}/custom_fields":
    get:
      summary: List seller custom fields
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the seller's custom field values.

        **Required scope:** `read_sellers` (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.sellers.customFields.list('sel_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /sellers/{seller_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: seller_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/stock_transfers/{stock_transfer_id}/custom_fields":
    get:
      summary: List stock transfer custom fields
      tags:
      - Stock Transfers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the stock transfer's custom field values.

        **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: customFields } = await client.customFields('stock_transfer', 'st_UkLWZg9DAJ').list()
      - lang: bash
        label: Spree CLI
        source: spree api get /stock_transfers/{stock_transfer_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: stock_transfer_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/purchase_orders/{purchase_order_id}/custom_fields":
    get:
      summary: List purchase order custom fields
      tags:
      - Purchase Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the purchase order's custom field values.

        **Required scope:** `read_purchasing` (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.customFields('purchase_order', 'po_UkLWZg9DAJ').list()
      - lang: bash
        label: Spree CLI
        source: spree api get /purchase_orders/{purchase_order_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: purchase_order_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/companies/{company_id}/custom_fields":
    get:
      summary: List company custom fields
      tags:
      - Companies
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the company's custom field values.

        **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: customFields } = await client.customFields('company', 'comp_UkLWZg9DAJ').list()
      - lang: bash
        label: Spree CLI
        source: spree api get /companies/{company_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: company_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/delivery_methods/{delivery_method_id}/custom_fields":
    get:
      summary: List delivery method custom fields
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the delivery method's custom field values.

        **Required scope:** `read_delivery_methods` (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.customFields('delivery_method', 'dm_UkLWZg9DAJ').list()
      - lang: bash
        label: Spree CLI
        source: spree api get /delivery_methods/{delivery_method_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: delivery_method_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/product_types/{product_type_id}/custom_fields":
    get:
      summary: List product type custom fields
      tags:
      - Product Types
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the product type's custom field values.

        **Required scope:** `read_product_types` (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.customFields('product_type', 'pt_UkLWZg9DAJ').list()
      - lang: bash
        label: Spree CLI
        source: spree api get /product_types/{product_type_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: product_type_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/media/{medium_id}/custom_fields":
    get:
      summary: List media file custom fields
      tags:
      - Media
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the media file's custom field values.

        **Required scope:** `read_media` (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.customFields('media', 'media_UkLWZg9DAJ').list()
      - lang: bash
        label: Spree CLI
        source: spree api get /media/{medium_id}/custom_fields
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: medium_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
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: CustomField
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: custom fields found
          content:
            application/json:
              example:
                data:
                - id: cf_UkLWZg9DAJ
                  label: Title
                  field_type: short_text
                  key: custom.title
                  value: wool
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  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:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/CustomField"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/delivery_profiles":
    get:
      summary: List delivery profiles
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Fulfillment profiles group products with the stock locations, delivery zones and delivery methods that fulfill them. Every store has exactly one default profile.

        **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 profiles = await client.deliveryProfiles.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /delivery_profiles
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `name`, `position`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: DeliveryProfile
        sortable:
        - created_at
        - id
        - name
        - position
        - updated_at
      responses:
        '200':
          description: delivery profiles found
          content:
            application/json:
              example:
                data:
                - id: fp_UkLWZg9DAJ
                  name: General
                  default: true
                  position: 1
                  created_at: '2026-11-11T12:45:25.491Z'
                  updated_at: '2026-11-11T12:45:25.491Z'
                  kind: shipping
                  digital: false
                  offers_pickup: false
                  offers_shipping: false
                  stock_location_ids: []
                  origin_groups:
                  - id: og_UkLWZg9DAJ
                    name:
                    position: 1
                    stock_location_ids: []
                  products_count: 0
                  delivery_methods_count: 0
                  delivery_zones_count: 0
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Create a delivery profile
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Creates a delivery profile. `kind` selects the registered profile kind (shipping, digital, extension kinds); `stock_location_ids` limits fulfillment to those locations — empty means every store location.

        **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 profile = await client.deliveryProfiles.create({
            name: 'Oversized',
            stock_location_ids: ['sloc_86Rf07xd4z'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /delivery_profiles -d '{"name":"Oversized","stock_location_ids":["sloc_86Rf07xd4z"]}'
      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: delivery profile created
          content:
            application/json:
              example:
                id: fp_gbHJdmfrXB
                name: Oversized 1768478400.0
                default: false
                position: 2
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                kind: shipping
                digital: false
                offers_pickup: false
                offers_shipping: false
                stock_location_ids: []
                origin_groups:
                - id: og_gbHJdmfrXB
                  name:
                  position: 1
                  stock_location_ids: []
                products_count: 0
                delivery_methods_count: 0
                delivery_zones_count: 0
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DeliveryProfileCreateParams"
        required: true
  "/api/v3/admin/delivery_profiles/{delivery_profile_id}/origin_groups":
    parameters:
    - name: delivery_profile_id
      in: path
      required: true
      schema:
        type: string
    get:
      summary: List origin groups
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the profile's origin groups: the sets of warehouses that each quote their own delivery rates.

        **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: originGroups } = await client.deliveryProfiles.originGroups.list('fp_86Rf07xd4z')
      - lang: bash
        label: Spree CLI
        source: spree api get /delivery_profiles/{delivery_profile_id}/origin_groups
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `name`, `position`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: DeliveryOriginGroup
        sortable:
        - created_at
        - id
        - name
        - position
        - updated_at
      responses:
        '200':
          description: origin groups found
          content:
            application/json:
              example:
                data:
                - id: og_gbHJdmfrXB
                  name:
                  position: 1
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  delivery_profile_id: fp_gbHJdmfrXB
                  stock_location_ids: []
                  delivery_zones_count: 0
                  delivery_methods_count: 0
                - id: og_EfhxLZ9ck8
                  name: EU warehouse
                  position: 2
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  delivery_profile_id: fp_gbHJdmfrXB
                  stock_location_ids: []
                  delivery_zones_count: 0
                  delivery_methods_count: 0
                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/DeliveryOriginGroup"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Create an origin group
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Origin groups partition a profile's fulfillment origins: zones and methods belong to a group, so the same products can quote different rate tables per warehouse. `stock_location_ids` replaces the full membership; empty means every store location.

        **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 originGroup = await client.deliveryProfiles.originGroups.create('fp_86Rf07xd4z', {
            name: 'EU warehouse',
            stock_location_ids: ['sloc_86Rf07xd4z'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /delivery_profiles/{delivery_profile_id}/origin_groups
          -d '{"name":"EU warehouse","stock_location_ids":["sloc_86Rf07xd4z"]}'
      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: origin group created
          content:
            application/json:
              example:
                id: og_EfhxLZ9ck8
                name: EU warehouse
                position: 2
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivery_profile_id: fp_gbHJdmfrXB
                stock_location_ids:
                - sloc_UkLWZg9DAJ
                delivery_zones_count: 0
                delivery_methods_count: 0
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DeliveryOriginGroupParams"
        required: true
  "/api/v3/admin/delivery_profiles/{id}":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
    patch:
      summary: Update a delivery profile
      tags:
      - Delivery
      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 profile = await client.deliveryProfiles.update('fp_86Rf07xd4z', {
            name: 'Oversized freight',
            stock_location_ids: [],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /delivery_profiles/{id} -d '{"name":"Oversized freight","stock_location_ids":[]}'
      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: delivery profile updated
          content:
            application/json:
              example:
                id: fp_gbHJdmfrXB
                name: Bulky 1768478400.0
                default: false
                position: 2
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                kind: shipping
                digital: false
                offers_pickup: false
                offers_shipping: false
                stock_location_ids:
                - sloc_UkLWZg9DAJ
                origin_groups:
                - id: og_gbHJdmfrXB
                  name:
                  position: 1
                  stock_location_ids:
                  - sloc_UkLWZg9DAJ
                products_count: 0
                delivery_methods_count: 0
                delivery_zones_count: 0
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DeliveryProfileUpdateParams"
        required: true
    delete:
      summary: Delete a delivery profile
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The default profile and profiles still referenced by products cannot be deleted.

        **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.deliveryProfiles.delete('fp_86Rf07xd4z')
      - lang: bash
        label: Spree CLI
        source: spree api delete /delivery_profiles/{id}
      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: delivery profile deleted
  "/api/v3/admin/delivery_methods":
    get:
      summary: List delivery methods
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns all delivery methods with calculator and zone configuration.

        **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: deliveryMethods } = await client.deliveryMethods.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /delivery_methods
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `available_to_sellers` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `seller_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `storefront_visible` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[seller_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |

          </Accordion>

          **Sort by:** `available_to_sellers`, `created_at`, `id`, `name`, `seller_id`, `storefront_visible`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: DeliveryMethod
        sortable:
        - available_to_sellers
        - created_at
        - id
        - name
        - seller_id
        - storefront_visible
        - updated_at
      responses:
        '200':
          description: delivery methods found
          content:
            application/json:
              example:
                data:
                - id: dm_UkLWZg9DAJ
                  name: UPS Ground
                  code: UPS_GROUND_12
                  estimated_transit_business_days_min:
                  estimated_transit_business_days_max:
                  digital: false
                  pickup: false
                  pickup_point: false
                  admin_name:
                  storefront_visible: true
                  tracking_url:
                  available_to_sellers: false
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  deleted_at:
                  markup_flat: '0.00'
                  markup_percent: '0'
                  seller_id:
                  seller_name:
                  services: []
                  rules: []
                  tax_category_id:
                  delivery_profile_id: fp_UkLWZg9DAJ
                  delivery_origin_group_id: og_UkLWZg9DAJ
                  delivery_zone_id:
                  stock_location_ids: []
                  fulfillment_provider: manual
                  pickup_point_provider:
                  rate_provider:
                  calculator:
                    type: flat_rate
                    preferences:
                      amounts: {}
                      amount: '10.00'
                      currency: USD
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Create delivery method
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Creates a delivery method inside a delivery profile (defaults to the store default profile). Delivery behavior comes from the fulfillment provider.

        **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 deliveryMethod = await client.deliveryMethods.create({
            name: 'Express',
            storefront_visible: true,
            calculator: { type: 'flat_rate', preferences: { amount: '12.50' } },
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /delivery_methods -d '{"name":"Express","storefront_visible":true,"calculator":{"type":"flat_rate","preferences":{"amount":"12.50"}}}'
      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: delivery method created
          content:
            application/json:
              example:
                id: dm_UkLWZg9DAJ
                name: Express
                code:
                estimated_transit_business_days_min:
                estimated_transit_business_days_max:
                digital: false
                pickup: false
                pickup_point: false
                admin_name:
                storefront_visible: true
                tracking_url:
                available_to_sellers: false
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                markup_flat: '0.00'
                markup_percent: '0'
                seller_id:
                seller_name:
                services: []
                rules: []
                tax_category_id:
                delivery_profile_id: fp_UkLWZg9DAJ
                delivery_origin_group_id: og_UkLWZg9DAJ
                delivery_zone_id:
                stock_location_ids: []
                fulfillment_provider: manual
                pickup_point_provider:
                rate_provider:
                calculator:
                  type: flat_rate
                  preferences:
                    amounts: {}
                    amount: '12.50'
                    currency: USD
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DeliveryMethodCreateParams"
        required: true
  "/api/v3/admin/delivery_methods/{id}":
    patch:
      summary: Update delivery method
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Updates a delivery method. Only the attributes sent change.

        **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 deliveryMethod = await client.deliveryMethods.update('dm_UkLWZg9DAJ', {
            name: 'UPS Express',
            estimated_transit_business_days_min: 1,
            estimated_transit_business_days_max: 2,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /delivery_methods/{id} -d '{"name":"UPS Express","estimated_transit_business_days_min":1,"estimated_transit_business_days_max":2}'
      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: delivery method updated
          content:
            application/json:
              example:
                id: dm_UkLWZg9DAJ
                name: UPS Express
                code: UPS_GROUND_13
                estimated_transit_business_days_min: 1
                estimated_transit_business_days_max: 2
                digital: false
                pickup: false
                pickup_point: false
                admin_name:
                storefront_visible: true
                tracking_url:
                available_to_sellers: false
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                markup_flat: '0.00'
                markup_percent: '0'
                seller_id:
                seller_name:
                services: []
                rules: []
                tax_category_id:
                delivery_profile_id: fp_UkLWZg9DAJ
                delivery_origin_group_id: og_UkLWZg9DAJ
                delivery_zone_id:
                stock_location_ids: []
                fulfillment_provider: manual
                pickup_point_provider:
                rate_provider:
                calculator:
                  type: flat_rate
                  preferences:
                    amounts: {}
                    amount: '10.00'
                    currency: USD
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DeliveryMethodUpdateParams"
        required: true
  "/api/v3/admin/delivery_methods/calculators":
    get:
      summary: List delivery calculators
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Registered delivery calculator classes with preference schemas for building configuration forms.

        **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 { data: calculators } = await client.deliveryMethods.calculators()
      - lang: bash
        label: Spree CLI
        source: spree api get /delivery_methods/calculators
      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: calculators found
          content:
            application/json:
              example:
                data:
                - type: flat_percent_item_total
                  name: Flat Percent
                  schema:
                    type: object
                    properties:
                      flat_percent:
                        type: string
                        pattern: "^-?\\d+(\\.\\d+)?$"
                        default: '0'
                    additionalProperties: false
                - type: flat_rate
                  name: Flat rate
                  schema:
                    type: object
                    properties:
                      amounts:
                        type: object
                        propertyNames:
                          type: string
                          format: currency
                          pattern: "^[A-Z]{3}$"
                        additionalProperties:
                          type: string
                          format: money
                          pattern: "^-?\\d+(\\.\\d+)?$"
                        default: {}
                      amount:
                        type:
                        - string
                        - 'null'
                        format: money
                        pattern: "^-?\\d+(\\.\\d+)?$"
                        default: '0'
                      currency:
                        type: string
                        format: currency
                        pattern: "^[A-Z]{3}$"
                    additionalProperties: false
                - type: flexi_rate
                  name: Flexible Rate per package item
                  schema:
                    type: object
                    properties:
                      first_item:
                        type: string
                        format: money
                        pattern: "^-?\\d+(\\.\\d+)?$"
                        default: '0'
                      additional_item:
                        type: string
                        format: money
                        pattern: "^-?\\d+(\\.\\d+)?$"
                        default: '0'
                      max_items:
                        type: integer
                        default: 0
                      currency:
                        type: string
                        format: currency
                        pattern: "^[A-Z]{3}$"
                    additionalProperties: false
                - type: per_item
                  name: Flat rate per package item
                  schema:
                    type: object
                    properties:
                      amounts:
                        type: object
                        propertyNames:
                          type: string
                          format: currency
                          pattern: "^[A-Z]{3}$"
                        additionalProperties:
                          type: string
                          format: money
                          pattern: "^-?\\d+(\\.\\d+)?$"
                        default: {}
                      amount:
                        type:
                        - string
                        - 'null'
                        format: money
                        pattern: "^-?\\d+(\\.\\d+)?$"
                        default: '0'
                      currency:
                        type: string
                        format: currency
                        pattern: "^[A-Z]{3}$"
                    additionalProperties: false
                - type: price_sack
                  name: Price sack
                  schema:
                    type: object
                    properties:
                      minimal_amount:
                        type: string
                        format: money
                        pattern: "^-?\\d+(\\.\\d+)?$"
                        default: '0'
                      normal_amount:
                        type: string
                        format: money
                        pattern: "^-?\\d+(\\.\\d+)?$"
                        default: '0'
                      discount_amount:
                        type: string
                        format: money
                        pattern: "^-?\\d+(\\.\\d+)?$"
                        default: '0'
                      currency:
                        type: string
                        format: currency
                        pattern: "^[A-Z]{3}$"
                    additionalProperties: false
                - type: digital_delivery
                  name: Digital Delivery
                  schema:
                    type: object
                    properties:
                      amounts:
                        type: object
                        propertyNames:
                          type: string
                          format: currency
                          pattern: "^[A-Z]{3}$"
                        additionalProperties:
                          type: string
                          format: money
                          pattern: "^-?\\d+(\\.\\d+)?$"
                        default: {}
                      amount:
                        type:
                        - string
                        - 'null'
                        format: money
                        pattern: "^-?\\d+(\\.\\d+)?$"
                        default: '0'
                      currency:
                        type: string
                        format: currency
                        pattern: "^[A-Z]{3}$"
                    additionalProperties: false
  "/api/v3/admin/delivery_zones":
    get:
      summary: List delivery zones
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the areas delivery methods ship to, each made of countries, states or postal code ranges.

        **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: deliveryZones } = await client.deliveryZones.list({ name_cont: 'US' })
      - lang: bash
        label: Spree CLI
        source: spree api get /delivery_zones -d '{"name_cont":"US"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `delivery_profile_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `delivery_profile_id`, `id`, `name`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: DeliveryZone
        sortable:
        - created_at
        - delivery_profile_id
        - id
        - name
        - updated_at
      responses:
        '200':
          description: delivery zones found
          content:
            application/json:
              example:
                data:
                - id: dz_UkLWZg9DAJ
                  name: US North-East
                  description: Natus fugiat numquam perferendis sint reiciendis.
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  delivery_profile_id: fp_UkLWZg9DAJ
                  delivery_origin_group_id: og_UkLWZg9DAJ
                  delivery_method_ids: []
                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/DeliveryZone"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Create delivery zone
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Creates a delivery zone with typed members: country, state, or postal_code (prefix or from/to range).

        **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 deliveryZone = await client.deliveryZones.create({
            name: 'US North-East',
            members: [
              { member_type: 'country', country_code: 'US' },
              { member_type: 'postal_code', country_code: 'US', postal_code_prefix: '10' },
            ],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /delivery_zones -d '{"name":"US North-East","members":[{"member_type":"country","country_code":"US"},{"member_type":"postal_code","country_code":"US","postal_code_prefix":"10"}]}'
      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, e.g. `members`
        schema:
          type: string
      responses:
        '201':
          description: delivery zone created
          content:
            application/json:
              example:
                id: dz_UkLWZg9DAJ
                name: US North-East
                description:
                members:
                - id: dzm_UkLWZg9DAJ
                  member_type: country
                  country_code: US
                  state_code:
                  postal_code_prefix:
                  postal_code_from:
                  postal_code_to:
                  country_name: United States
                  state_name:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                - id: dzm_gbHJdmfrXB
                  member_type: postal_code
                  country_code: US
                  state_code:
                  postal_code_prefix: '10'
                  postal_code_from:
                  postal_code_to:
                  country_name: United States
                  state_name:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivery_profile_id: fp_UkLWZg9DAJ
                delivery_origin_group_id: og_UkLWZg9DAJ
                delivery_method_ids: []
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DeliveryZoneCreateParams"
        required: true
  "/api/v3/admin/delivery_zones/{id}":
    patch:
      summary: Update delivery zone
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Updates a delivery zone. Sending `members` replaces the whole member list; leaving it out keeps the current members.

        **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',
          })

          // `members` replaces the zone's full member set.
          const deliveryZone = await client.deliveryZones.update('dz_UkLWZg9DAJ', {
            name: 'US East Coast',
            members: [
              {
                member_type: 'postal_code',
                country_code: 'US',
                postal_code_from: '10000',
                postal_code_to: '14999',
              },
            ],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /delivery_zones/{id} -d '{"name":"US East Coast","members":[{"member_type":"postal_code","country_code":"US","postal_code_from":"10000","postal_code_to":"14999"}]}'
      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 embed, e.g. `members`
        schema:
          type: string
      responses:
        '200':
          description: delivery zone updated
          content:
            application/json:
              example:
                id: dz_UkLWZg9DAJ
                name: US East Coast
                description: Omnis ipsam provident laboriosam est.
                members:
                - id: dzm_UkLWZg9DAJ
                  member_type: postal_code
                  country_code: US
                  state_code:
                  postal_code_prefix:
                  postal_code_from: '10000'
                  postal_code_to: '14999'
                  country_name: United States
                  state_name:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivery_profile_id: fp_UkLWZg9DAJ
                delivery_origin_group_id: og_UkLWZg9DAJ
                delivery_method_ids: []
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DeliveryZoneUpdateParams"
        required: true
  "/api/v3/admin/delivery_methods/{delivery_method_id}/rules":
    get:
      summary: List delivery method rules
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the conditions a delivery method must meet to be offered at checkout, such as an order total or weight range.

        **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: rules } = await client.deliveryMethods.rules.list('dm_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /delivery_methods/{delivery_method_id}/rules
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: delivery_method_id
        in: path
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: DeliveryMethodRule
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: rules found
          content:
            application/json:
              example:
                data:
                - id: dmrule_UkLWZg9DAJ
                  active: true
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  type: item_total_rule
                  preferences:
                    minimum_amount: '25'
                    maximum_amount:
                  product_ids: []
                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/DeliveryMethodRule"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Create a delivery method rule
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds a condition to a delivery method. `type` is a rule kind from the
        delivery method rule types endpoint, and `preferences` takes the
        values its schema declares.


        **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',
          })

          // Offer this method only on orders of 50.00 or more:
          const rule = await client.deliveryMethods.rules.create('dm_UkLWZg9DAJ', {
            type: 'item_total_rule',
            preferences: { minimum_amount: '50.00' },
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /delivery_methods/{delivery_method_id}/rules -d '{"type":"item_total_rule","preferences":{"minimum_amount":"50.00"}}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: delivery_method_id
        in: path
        required: true
        schema:
          type: string
      responses:
        '201':
          description: rule created
          content:
            application/json:
              example:
                id: dmrule_UkLWZg9DAJ
                active: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: item_total_rule
                preferences:
                  minimum_amount: '50'
                  maximum_amount:
                product_ids: []
              schema:
                "$ref": "#/components/schemas/DeliveryMethodRule"
        '422':
          description: unknown rule type
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: is not a registered delivery method rule
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DeliveryMethodRuleCreateParams"
        required: true
  "/api/v3/admin/delivery_methods/{delivery_method_id}/rules/{id}":
    patch:
      summary: Update a delivery method rule
      tags:
      - Delivery
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Changes a rule's settings or turns it off. Its `type` is fixed once created.

        **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 rule = await client.deliveryMethods.rules.update('dm_UkLWZg9DAJ', 'dmrule_UkLWZg9DAJ', {
            active: false,
            preferences: { minimum_amount: '40.00', maximum_amount: '500.00' },
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /delivery_methods/{delivery_method_id}/rules/{id}
          -d '{"active":false,"preferences":{"minimum_amount":"40.00","maximum_amount":"500.00"}}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: delivery_method_id
        in: path
        required: true
        schema:
          type: string
      - name: id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: rule updated
          content:
            application/json:
              example:
                id: dmrule_UkLWZg9DAJ
                active: false
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: item_total_rule
                preferences:
                  minimum_amount: '40'
                  maximum_amount: '500'
                product_ids: []
              schema:
                "$ref": "#/components/schemas/DeliveryMethodRule"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DeliveryMethodRuleUpdateParams"
        required: true
  "/api/v3/admin/integrations":
    get:
      summary: List integrations
      tags:
      - Integrations
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the integrations connected to the current store. Secret preference values are masked.

        **Required scope:** `read_integrations` (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: integrations } = await client.integrations.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /integrations
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Integration
        sortable:
        - created_at
        - id
        - updated_at
      responses:
        '200':
          description: integrations found
          content:
            application/json:
              example:
                data:
                - id: int_UkLWZg9DAJ
                  name: Carrier
                  active: false
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  type: carrier
                  group: shipping
                  preferences:
                    api_key: "•••••cret"
                    account_number: '42'
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Connect integration
      tags:
      - Integrations
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Connects an integration type to the current store. Setting active: true verifies the connection and fails with 422 when it cannot connect. Submitting a masked secret value back keeps the stored secret.

        **Required scope:** `write_integrations` (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 integration = await client.integrations.create({
            type: 'carrier',
            preferences: { api_key: 'sk-secret', account_number: '42' },
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /integrations -d '{"type":"carrier","preferences":{"api_key":"sk-secret","account_number":"42"}}'
      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: integration connected
          content:
            application/json:
              example:
                id: int_UkLWZg9DAJ
                name: Carrier
                active: false
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: carrier
                group: shipping
                preferences:
                  api_key: "•••••cret"
                  account_number:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/IntegrationCreateParams"
        required: true
  "/api/v3/admin/integrations/types":
    get:
      summary: List integration types
      tags:
      - Integrations
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Every registered integration type with its gallery metadata and configuration schema. Pure registry discovery — read live connection state from GET /integrations.

        **Required scope:** `read_integrations` (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: integrationTypes } = await client.integrations.types()
      - lang: bash
        label: Spree CLI
        source: spree api get /integrations/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: integration types found
          content:
            application/json:
              example:
                data:
                - type: carrier
                  name: Carrier
                  group: shipping
                  description:
                  logo_url:
                  docs_url:
                  schema:
                    type: object
                    properties:
                      api_key:
                        type:
                        - string
                        - 'null'
                        x-spree-secret: true
                      account_number:
                        type:
                        - string
                        - 'null'
                    additionalProperties: false
  "/api/v3/admin/integrations/{id}":
    patch:
      summary: Update integration
      tags:
      - Integrations
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Changes an integration's credentials or turns it on or off. Setting active: true verifies the connection and fails with 422 when it cannot connect. Submitting a masked secret value back keeps the stored secret.

        **Required scope:** `write_integrations` (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 integration = await client.integrations.update('int_UkLWZg9DAJ', {
            active: true,
            preferences: { account_number: 'demo-0001' },
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /integrations/{id} -d '{"active":true,"preferences":{"account_number":"demo-0001"}}'
      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: integration updated
          content:
            application/json:
              example:
                id: int_UkLWZg9DAJ
                name: Carrier
                active: true
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                type: carrier
                group: shipping
                preferences:
                  api_key: "•••••cret"
                  account_number: demo-0001
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/IntegrationUpdateParams"
        required: true
  "/api/v3/admin/integrations/{id}/test":
    post:
      summary: Test integration connection
      tags:
      - Integrations
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Runs a live connection check against the provider. Nothing is persisted; a failed check reports the seller error message.

        **Required scope:** `write_integrations` (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.integrations.test('int_abc123')
      - lang: bash
        label: Spree CLI
        source: spree api post /integrations/{id}/test -d '{ ... }'
      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: connection checked
          content:
            application/json:
              example:
                connected: true
                error_message:
  "/api/v3/admin/media":
    get:
      summary: List media
      tags:
      - Media
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns every file in the store's media library, whether or not it has
        been placed on a product. Filter with `q[unattached]=true` for files not
        yet in use, `q[media_type_eq]` for images or video, and
        `q[filename_cont]` to search by file name.


        **Required scope:** `read_media` (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',
          })

          // Library images that are not used anywhere yet.
          const { data: media } = await client.media.list({
            unattached: true,
            media_type_eq: 'image',
            limit: 25,
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /media -d '{"unattached":true,"media_type_eq":"image","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: q[attached]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `attached`.
      - name: q[filename_cont]
        in: query
        required: false
        schema:
          type: string
        description: Applies `filename_cont` to the given value.
      - name: q[unattached]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `unattached`.
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[alt_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `alt` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `byte_size` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `filename` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `media_type` | One of `image`, `video`, `external_video` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `alt`, `byte_size`, `created_at`, `filename`, `id`, `media_type`, `position`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Media
        sortable:
        - alt
        - byte_size
        - created_at
        - filename
        - id
        - media_type
        - position
        - updated_at
      responses:
        '200':
          description: media found
          content:
            application/json:
              example:
                data:
                - id: media_UkLWZg9DAJ
                  product_id: prod_UkLWZg9DAJ
                  variant_ids: []
                  position: 1
                  alt: Front view
                  media_type: image
                  external_video_url:
                  focal_point_x:
                  focal_point_y:
                  video_provider:
                  video_embed_url:
                  video_url:
                  poster_url:
                  original_url: http://localhost:3000/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/thinking-cat.jpg
                  mini_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsxMjgsMTI4XSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--f31d99c473e446770eab355d27021996d87a6b4f/thinking-cat.jpg
                  small_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsyNTYsMjU2XSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--723714d967fb303bdad1d3cf8ba94bf6558b4a10/thinking-cat.jpg
                  medium_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOls0MDAsNDAwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--36830faf4bdf4f022a94d4bdcc88de61440b6e33/thinking-cat.jpg
                  large_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOls3MjAsNzIwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--6c5f60a2dd3b4d1a2ab5f6103f86b22a64f5fd47/thinking-cat.jpg
                  xlarge_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsyMDAwLDIwMDBdLCJzYXZlciI6eyJzdHJpcCI6dHJ1ZSwicXVhbGl0eSI6NzUsImxvc3NsZXNzIjpmYWxzZSwiYWxwaGFfcSI6ODUsInJlZHVjdGlvbl9lZmZvcnQiOjYsInNtYXJ0X3N1YnNhbXBsZSI6dHJ1ZX19LCJwdXIiOiJ2YXJpYXRpb24ifX0=--6ce851493cd3ead1087cb140c9deecb4447d1142/thinking-cat.jpg
                  og_image_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsxMjAwLDYzMF0sInNhdmVyIjp7InN0cmlwIjp0cnVlLCJxdWFsaXR5Ijo3NSwibG9zc2xlc3MiOmZhbHNlLCJhbHBoYV9xIjo4NSwicmVkdWN0aW9uX2VmZm9ydCI6Niwic21hcnRfc3Vic2FtcGxlIjp0cnVlfX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--9485e3d0e9e9133d7c52af17e4392a9c6842a55d/thinking-cat.jpg
                  external_references: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  attached: true
                  filename: thinking-cat.jpg
                  content_type: image/jpeg
                  byte_size: 18090
                  embed_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbMTIwMCwxMjAwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--19f16573cafa934a908d21a80fef013aca3219fc/thinking-cat.jpg
                  signed_id: eyJfcmFpbHMiOnsiZGF0YSI6MSwiZXhwIjoiMjAyNi0wMS0xNlQxMjowMDowMC4wMDBaIiwicHVyIjoiYmxvYl9pZCJ9fQ==--5cf7f6bc12adaf5ef31072ed4b5eb4c1732ca992
                  viewable_id: prod_UkLWZg9DAJ
                  download_url: http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/thinking-cat.jpg?disposition=attachment
                  metadata: {}
                  viewable_type: product
                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/Media"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Upload a file to the library
      tags:
      - Media
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds a file to the library without placing it on anything. Upload the
        file first through `POST /api/v3/admin/files`, then send the signed id
        here. Put the file on a product by posting to that product's media with
        this record's id as `source_media_id`.


        **Required scope:** `write_media` (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',
          })

          // Upload the file first with `client.files.upload(file)`, then add it here.
          const media = await client.media.create({
            signed_id: 'eyJfcmFpbHMiOnsiZGF0YSI6NDJ9fQ==--8f3a2c',
            alt: 'Folded on a table',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /media -d '{"signed_id":"eyJfcmFpbHMiOnsiZGF0YSI6NDJ9fQ==--8f3a2c","alt":"Folded
          on a table"}'
      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: file added
          content:
            application/json:
              example:
                id: media_gbHJdmfrXB
                product_id:
                variant_ids: []
                position: 1
                alt: Folded on a table
                media_type: image
                external_video_url:
                focal_point_x:
                focal_point_y:
                video_provider:
                video_embed_url:
                video_url:
                poster_url:
                original_url: http://localhost:3000/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/library-upload.jpg
                mini_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsxMjgsMTI4XSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--f31d99c473e446770eab355d27021996d87a6b4f/library-upload.jpg
                small_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsyNTYsMjU2XSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--723714d967fb303bdad1d3cf8ba94bf6558b4a10/library-upload.jpg
                medium_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOls0MDAsNDAwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--36830faf4bdf4f022a94d4bdcc88de61440b6e33/library-upload.jpg
                large_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOls3MjAsNzIwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--6c5f60a2dd3b4d1a2ab5f6103f86b22a64f5fd47/library-upload.jpg
                xlarge_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsyMDAwLDIwMDBdLCJzYXZlciI6eyJzdHJpcCI6dHJ1ZSwicXVhbGl0eSI6NzUsImxvc3NsZXNzIjpmYWxzZSwiYWxwaGFfcSI6ODUsInJlZHVjdGlvbl9lZmZvcnQiOjYsInNtYXJ0X3N1YnNhbXBsZSI6dHJ1ZX19LCJwdXIiOiJ2YXJpYXRpb24ifX0=--6ce851493cd3ead1087cb140c9deecb4447d1142/library-upload.jpg
                og_image_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsxMjAwLDYzMF0sInNhdmVyIjp7InN0cmlwIjp0cnVlLCJxdWFsaXR5Ijo3NSwibG9zc2xlc3MiOmZhbHNlLCJhbHBoYV9xIjo4NSwicmVkdWN0aW9uX2VmZm9ydCI6Niwic21hcnRfc3Vic2FtcGxlIjp0cnVlfX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--9485e3d0e9e9133d7c52af17e4392a9c6842a55d/library-upload.jpg
                external_references: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                attached: false
                filename: library-upload.jpg
                content_type: image/jpeg
                byte_size: 18090
                embed_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbMTIwMCwxMjAwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--19f16573cafa934a908d21a80fef013aca3219fc/library-upload.jpg
                signed_id: eyJfcmFpbHMiOnsiZGF0YSI6MiwiZXhwIjoiMjAyNi0wMS0xNlQxMjowMDowMC4wMDBaIiwicHVyIjoiYmxvYl9pZCJ9fQ==--e50a78b4c158cae84263a776c40322cc8b7b0b57
                viewable_id:
                download_url: http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/library-upload.jpg?disposition=attachment
                metadata: {}
                viewable_type:
              schema:
                "$ref": "#/components/schemas/Media"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/MediaLibraryCreateParams"
        required: true
  "/api/v3/admin/media/{id}":
    parameters:
    - name: id
      in: path
      description: Media ID
      required: true
      schema:
        type: string
    patch:
      summary: Update a library file
      tags:
      - Media
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Edits a file in the library, such as its alt text.

        **Required scope:** `write_media` (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 media = await client.media.update('media_UkLWZg9DAJ', {
            alt: 'Folded on a table',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /media/{id} -d '{"alt":"Folded on a table"}'
      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: file updated
          content:
            application/json:
              example:
                id: media_UkLWZg9DAJ
                product_id: prod_UkLWZg9DAJ
                variant_ids: []
                position: 1
                alt: Folded on a table
                media_type: image
                external_video_url:
                focal_point_x:
                focal_point_y:
                video_provider:
                video_embed_url:
                video_url:
                poster_url:
                original_url: http://localhost:3000/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/thinking-cat.jpg
                mini_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsxMjgsMTI4XSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--f31d99c473e446770eab355d27021996d87a6b4f/thinking-cat.jpg
                small_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsyNTYsMjU2XSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--723714d967fb303bdad1d3cf8ba94bf6558b4a10/thinking-cat.jpg
                medium_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOls0MDAsNDAwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--36830faf4bdf4f022a94d4bdcc88de61440b6e33/thinking-cat.jpg
                large_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOls3MjAsNzIwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--6c5f60a2dd3b4d1a2ab5f6103f86b22a64f5fd47/thinking-cat.jpg
                xlarge_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsyMDAwLDIwMDBdLCJzYXZlciI6eyJzdHJpcCI6dHJ1ZSwicXVhbGl0eSI6NzUsImxvc3NsZXNzIjpmYWxzZSwiYWxwaGFfcSI6ODUsInJlZHVjdGlvbl9lZmZvcnQiOjYsInNtYXJ0X3N1YnNhbXBsZSI6dHJ1ZX19LCJwdXIiOiJ2YXJpYXRpb24ifX0=--6ce851493cd3ead1087cb140c9deecb4447d1142/thinking-cat.jpg
                og_image_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsxMjAwLDYzMF0sInNhdmVyIjp7InN0cmlwIjp0cnVlLCJxdWFsaXR5Ijo3NSwibG9zc2xlc3MiOmZhbHNlLCJhbHBoYV9xIjo4NSwicmVkdWN0aW9uX2VmZm9ydCI6Niwic21hcnRfc3Vic2FtcGxlIjp0cnVlfX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--9485e3d0e9e9133d7c52af17e4392a9c6842a55d/thinking-cat.jpg
                external_references: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                attached: true
                filename: thinking-cat.jpg
                content_type: image/jpeg
                byte_size: 18090
                embed_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbMTIwMCwxMjAwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--19f16573cafa934a908d21a80fef013aca3219fc/thinking-cat.jpg
                signed_id: eyJfcmFpbHMiOnsiZGF0YSI6MSwiZXhwIjoiMjAyNi0wMS0xNlQxMjowMDowMC4wMDBaIiwicHVyIjoiYmxvYl9pZCJ9fQ==--5cf7f6bc12adaf5ef31072ed4b5eb4c1732ca992
                viewable_id: prod_UkLWZg9DAJ
                download_url: http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/thinking-cat.jpg?disposition=attachment
                metadata: {}
                viewable_type: product
              schema:
                "$ref": "#/components/schemas/Media"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/MediaLibraryUpdateParams"
        required: true
  "/api/v3/admin/media/{id}/usage":
    parameters:
    - name: id
      in: path
      description: Media ID
      required: true
      schema:
        type: string
    get:
      summary: Where a file is used
      tags:
      - Media
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Lists everywhere this file appears: products it is placed on, image
        fields that picked it, and descriptions embedding it. Reusing a file
        shares it rather than copying it, so deleting one placement can leave
        others pointing at the same file — check this first.

        Description matches are best-effort: an embedded image is a plain URL
        with nothing recording it, so treat an empty result as "nothing found",
        not proof the file is unused.


        **Required scope:** `read_media` (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',
          })

          // Check where a file is used before deleting it.
          const { data: usage } = await client.media.usage('media_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /media/{id}/usage
      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: usage found
          content:
            application/json:
              example:
                data:
                - kind: media
                  name: Product 483397
                  owner_type: product
                  owner_id: prod_UkLWZg9DAJ
                  field: attachment
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        kind:
                          type: string
                          enum:
                          - media
                          - attachment
                          - rich_text
                        name:
                          type: string
                          nullable: true
                        owner_type:
                          type: string
                        owner_id:
                          type: string
                          nullable: true
                        field:
                          type: string
                          nullable: true
  "/api/v3/admin/products/{product_id}/media":
    parameters:
    - name: product_id
      in: path
      description: Product ID
      required: true
      schema:
        type: string
    get:
      summary: List product media
      tags:
      - Media
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the files placed on a product, in their display order.

        **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: media } = await client.products.media.list('prod_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /products/{product_id}/media
      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: q[attached]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `attached`.
      - name: q[filename_cont]
        in: query
        required: false
        schema:
          type: string
        description: Applies `filename_cont` to the given value.
      - name: q[unattached]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `unattached`.
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[alt_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `alt` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `byte_size` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `filename` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `media_type` | One of `image`, `video`, `external_video` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `alt`, `byte_size`, `created_at`, `filename`, `id`, `media_type`, `position`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Media
        sortable:
        - alt
        - byte_size
        - created_at
        - filename
        - id
        - media_type
        - position
        - updated_at
      responses:
        '200':
          description: media found
          content:
            application/json:
              example:
                data:
                - id: media_UkLWZg9DAJ
                  product_id: prod_UkLWZg9DAJ
                  variant_ids: []
                  position: 1
                  alt: Front view
                  media_type: image
                  external_video_url:
                  focal_point_x:
                  focal_point_y:
                  video_provider:
                  video_embed_url:
                  video_url:
                  poster_url:
                  original_url: http://localhost:3000/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/thinking-cat.jpg
                  mini_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsxMjgsMTI4XSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--f31d99c473e446770eab355d27021996d87a6b4f/thinking-cat.jpg
                  small_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsyNTYsMjU2XSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--723714d967fb303bdad1d3cf8ba94bf6558b4a10/thinking-cat.jpg
                  medium_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOls0MDAsNDAwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--36830faf4bdf4f022a94d4bdcc88de61440b6e33/thinking-cat.jpg
                  large_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOls3MjAsNzIwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--6c5f60a2dd3b4d1a2ab5f6103f86b22a64f5fd47/thinking-cat.jpg
                  xlarge_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsyMDAwLDIwMDBdLCJzYXZlciI6eyJzdHJpcCI6dHJ1ZSwicXVhbGl0eSI6NzUsImxvc3NsZXNzIjpmYWxzZSwiYWxwaGFfcSI6ODUsInJlZHVjdGlvbl9lZmZvcnQiOjYsInNtYXJ0X3N1YnNhbXBsZSI6dHJ1ZX19LCJwdXIiOiJ2YXJpYXRpb24ifX0=--6ce851493cd3ead1087cb140c9deecb4447d1142/thinking-cat.jpg
                  og_image_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsxMjAwLDYzMF0sInNhdmVyIjp7InN0cmlwIjp0cnVlLCJxdWFsaXR5Ijo3NSwibG9zc2xlc3MiOmZhbHNlLCJhbHBoYV9xIjo4NSwicmVkdWN0aW9uX2VmZm9ydCI6Niwic21hcnRfc3Vic2FtcGxlIjp0cnVlfX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--9485e3d0e9e9133d7c52af17e4392a9c6842a55d/thinking-cat.jpg
                  external_references: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  attached: true
                  filename: thinking-cat.jpg
                  content_type: image/jpeg
                  byte_size: 18090
                  embed_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbMTIwMCwxMjAwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--19f16573cafa934a908d21a80fef013aca3219fc/thinking-cat.jpg
                  signed_id: eyJfcmFpbHMiOnsiZGF0YSI6MSwiZXhwIjoiMjAyNi0wMS0xNlQxMjowMDowMC4wMDBaIiwicHVyIjoiYmxvYl9pZCJ9fQ==--5cf7f6bc12adaf5ef31072ed4b5eb4c1732ca992
                  viewable_id: prod_UkLWZg9DAJ
                  download_url: http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/thinking-cat.jpg?disposition=attachment
                  metadata: {}
                  viewable_type: product
                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/Media"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Place a library file on a product
      tags:
      - Media
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Puts a file that is already in the library onto this product. The new
        record shares the source's file rather than copying it, so nothing is
        uploaded and no image is reprocessed; it carries its own alt text,
        position and variant links from here on.


        **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',
          })

          // Places a library file on the product. The file is shared, not copied.
          const media = await client.products.media.create('prod_UkLWZg9DAJ', {
            source_media_id: 'media_UkLWZg9DAJ',
            alt: 'Front view',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /products/{product_id}/media -d '{"source_media_id":"media_UkLWZg9DAJ","alt":"Front
          view"}'
      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: file placed
          content:
            application/json:
              example:
                id: media_gbHJdmfrXB
                product_id: prod_gbHJdmfrXB
                variant_ids: []
                position: 1
                alt: Front view
                media_type: image
                external_video_url:
                focal_point_x:
                focal_point_y:
                video_provider:
                video_embed_url:
                video_url:
                poster_url:
                original_url: http://localhost:3000/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/thinking-cat.jpg
                mini_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsxMjgsMTI4XSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--f31d99c473e446770eab355d27021996d87a6b4f/thinking-cat.jpg
                small_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsyNTYsMjU2XSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--723714d967fb303bdad1d3cf8ba94bf6558b4a10/thinking-cat.jpg
                medium_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOls0MDAsNDAwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--36830faf4bdf4f022a94d4bdcc88de61440b6e33/thinking-cat.jpg
                large_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOls3MjAsNzIwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--6c5f60a2dd3b4d1a2ab5f6103f86b22a64f5fd47/thinking-cat.jpg
                xlarge_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsyMDAwLDIwMDBdLCJzYXZlciI6eyJzdHJpcCI6dHJ1ZSwicXVhbGl0eSI6NzUsImxvc3NsZXNzIjpmYWxzZSwiYWxwaGFfcSI6ODUsInJlZHVjdGlvbl9lZmZvcnQiOjYsInNtYXJ0X3N1YnNhbXBsZSI6dHJ1ZX19LCJwdXIiOiJ2YXJpYXRpb24ifX0=--6ce851493cd3ead1087cb140c9deecb4447d1142/thinking-cat.jpg
                og_image_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsxMjAwLDYzMF0sInNhdmVyIjp7InN0cmlwIjp0cnVlLCJxdWFsaXR5Ijo3NSwibG9zc2xlc3MiOmZhbHNlLCJhbHBoYV9xIjo4NSwicmVkdWN0aW9uX2VmZm9ydCI6Niwic21hcnRfc3Vic2FtcGxlIjp0cnVlfX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--9485e3d0e9e9133d7c52af17e4392a9c6842a55d/thinking-cat.jpg
                external_references: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                attached: true
                filename: thinking-cat.jpg
                content_type: image/jpeg
                byte_size: 18090
                embed_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbMTIwMCwxMjAwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--19f16573cafa934a908d21a80fef013aca3219fc/thinking-cat.jpg
                signed_id: eyJfcmFpbHMiOnsiZGF0YSI6MSwiZXhwIjoiMjAyNi0wMS0xNlQxMjowMDowMC4wMDBaIiwicHVyIjoiYmxvYl9pZCJ9fQ==--5cf7f6bc12adaf5ef31072ed4b5eb4c1732ca992
                viewable_id: prod_gbHJdmfrXB
                download_url: http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/thinking-cat.jpg?disposition=attachment
                metadata: {}
                viewable_type: product
              schema:
                "$ref": "#/components/schemas/Media"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/MediaCreateParams"
        required: true
  "/api/v3/admin/products/{product_id}/media/{id}":
    parameters:
    - name: product_id
      in: path
      description: Product ID
      required: true
      schema:
        type: string
    - name: id
      in: path
      description: Media ID
      required: true
      schema:
        type: string
    patch:
      summary: Update product media
      tags:
      - Media
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Edits a file placed on a product: its alt text, position and focal
        point, and which of the product's variants it shows for
        (`variant_ids`).


        **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 media = await client.products.media.update('prod_UkLWZg9DAJ', 'media_gbHJdmfrXB', {
            alt: 'Side view',
            position: 1,
            variant_ids: ['variant_UkLWZg9DAJ'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /products/{product_id}/media/{id} -d '{"alt":"Side
          view","position":1,"variant_ids":["variant_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:
        '200':
          description: media updated
          content:
            application/json:
              example:
                id: media_UkLWZg9DAJ
                product_id: prod_UkLWZg9DAJ
                variant_ids: []
                position: 1
                alt: Side view
                media_type: image
                external_video_url:
                focal_point_x:
                focal_point_y:
                video_provider:
                video_embed_url:
                video_url:
                poster_url:
                original_url: http://localhost:3000/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/thinking-cat.jpg
                mini_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsxMjgsMTI4XSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--f31d99c473e446770eab355d27021996d87a6b4f/thinking-cat.jpg
                small_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsyNTYsMjU2XSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--723714d967fb303bdad1d3cf8ba94bf6558b4a10/thinking-cat.jpg
                medium_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOls0MDAsNDAwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--36830faf4bdf4f022a94d4bdcc88de61440b6e33/thinking-cat.jpg
                large_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOls3MjAsNzIwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--6c5f60a2dd3b4d1a2ab5f6103f86b22a64f5fd47/thinking-cat.jpg
                xlarge_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsyMDAwLDIwMDBdLCJzYXZlciI6eyJzdHJpcCI6dHJ1ZSwicXVhbGl0eSI6NzUsImxvc3NsZXNzIjpmYWxzZSwiYWxwaGFfcSI6ODUsInJlZHVjdGlvbl9lZmZvcnQiOjYsInNtYXJ0X3N1YnNhbXBsZSI6dHJ1ZX19LCJwdXIiOiJ2YXJpYXRpb24ifX0=--6ce851493cd3ead1087cb140c9deecb4447d1142/thinking-cat.jpg
                og_image_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsxMjAwLDYzMF0sInNhdmVyIjp7InN0cmlwIjp0cnVlLCJxdWFsaXR5Ijo3NSwibG9zc2xlc3MiOmZhbHNlLCJhbHBoYV9xIjo4NSwicmVkdWN0aW9uX2VmZm9ydCI6Niwic21hcnRfc3Vic2FtcGxlIjp0cnVlfX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--9485e3d0e9e9133d7c52af17e4392a9c6842a55d/thinking-cat.jpg
                external_references: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                attached: true
                filename: thinking-cat.jpg
                content_type: image/jpeg
                byte_size: 18090
                embed_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbMTIwMCwxMjAwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--19f16573cafa934a908d21a80fef013aca3219fc/thinking-cat.jpg
                signed_id: eyJfcmFpbHMiOnsiZGF0YSI6MSwiZXhwIjoiMjAyNi0wMS0xNlQxMjowMDowMC4wMDBaIiwicHVyIjoiYmxvYl9pZCJ9fQ==--5cf7f6bc12adaf5ef31072ed4b5eb4c1732ca992
                viewable_id: prod_UkLWZg9DAJ
                download_url: http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsiZGF0YSI6MSwicHVyIjoiYmxvYl9pZCJ9fQ==--fe5cbf0b8d6bb2970dbcc5053623661df3d2054f/thinking-cat.jpg?disposition=attachment
                metadata: {}
                viewable_type: product
              schema:
                "$ref": "#/components/schemas/Media"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/MediaUpdateParams"
        required: true
  "/api/v3/admin/products/{product_id}/variants/{variant_id}/media":
    parameters:
    - name: product_id
      in: path
      description: Product ID
      required: true
      schema:
        type: string
    - name: variant_id
      in: path
      description: Variant ID
      required: true
      schema:
        type: string
    get:
      summary: List variant media
      tags:
      - Media
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the files placed on one of a product's variants, in their display order.

        **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: media } = await client.products.variants.media.list(
            'prod_UkLWZg9DAJ',
            'variant_UkLWZg9DAJ',
          )
      - lang: bash
        label: Spree CLI
        source: spree api get /products/{product_id}/variants/{variant_id}/media
      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: q[attached]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `attached`.
      - name: q[filename_cont]
        in: query
        required: false
        schema:
          type: string
        description: Applies `filename_cont` to the given value.
      - name: q[unattached]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `unattached`.
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[alt_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `alt` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `byte_size` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `filename` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `media_type` | One of `image`, `video`, `external_video` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `alt`, `byte_size`, `created_at`, `filename`, `id`, `media_type`, `position`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Media
        sortable:
        - alt
        - byte_size
        - created_at
        - filename
        - id
        - media_type
        - position
        - updated_at
      responses:
        '200':
          description: media found
          content:
            application/json:
              example:
                data:
                - id: media_gbHJdmfrXB
                  product_id: prod_UkLWZg9DAJ
                  variant_ids:
                  - variant_gbHJdmfrXB
                  position: 1
                  alt: Variant view
                  media_type: image
                  external_video_url:
                  focal_point_x:
                  focal_point_y:
                  video_provider:
                  video_embed_url:
                  video_url:
                  poster_url:
                  original_url: http://localhost:3000/rails/active_storage/blobs/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/thinking-cat.jpg
                  mini_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsxMjgsMTI4XSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--f31d99c473e446770eab355d27021996d87a6b4f/thinking-cat.jpg
                  small_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsyNTYsMjU2XSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--723714d967fb303bdad1d3cf8ba94bf6558b4a10/thinking-cat.jpg
                  medium_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOls0MDAsNDAwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--36830faf4bdf4f022a94d4bdcc88de61440b6e33/thinking-cat.jpg
                  large_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOls3MjAsNzIwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--6c5f60a2dd3b4d1a2ab5f6103f86b22a64f5fd47/thinking-cat.jpg
                  xlarge_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsyMDAwLDIwMDBdLCJzYXZlciI6eyJzdHJpcCI6dHJ1ZSwicXVhbGl0eSI6NzUsImxvc3NsZXNzIjpmYWxzZSwiYWxwaGFfcSI6ODUsInJlZHVjdGlvbl9lZmZvcnQiOjYsInNtYXJ0X3N1YnNhbXBsZSI6dHJ1ZX19LCJwdXIiOiJ2YXJpYXRpb24ifX0=--6ce851493cd3ead1087cb140c9deecb4447d1142/thinking-cat.jpg
                  og_image_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2ZpbGwiOlsxMjAwLDYzMF0sInNhdmVyIjp7InN0cmlwIjp0cnVlLCJxdWFsaXR5Ijo3NSwibG9zc2xlc3MiOmZhbHNlLCJhbHBoYV9xIjo4NSwicmVkdWN0aW9uX2VmZm9ydCI6Niwic21hcnRfc3Vic2FtcGxlIjp0cnVlfX0sInB1ciI6InZhcmlhdGlvbiJ9fQ==--9485e3d0e9e9133d7c52af17e4392a9c6842a55d/thinking-cat.jpg
                  external_references: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  attached: true
                  filename: thinking-cat.jpg
                  content_type: image/jpeg
                  byte_size: 18090
                  embed_url: http://localhost:3000/rails/active_storage/representations/proxy/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/eyJfcmFpbHMiOnsiZGF0YSI6eyJmb3JtYXQiOiJ3ZWJwIiwicmVzaXplX3RvX2xpbWl0IjpbMTIwMCwxMjAwXSwic2F2ZXIiOnsic3RyaXAiOnRydWUsInF1YWxpdHkiOjc1LCJsb3NzbGVzcyI6ZmFsc2UsImFscGhhX3EiOjg1LCJyZWR1Y3Rpb25fZWZmb3J0Ijo2LCJzbWFydF9zdWJzYW1wbGUiOnRydWV9fSwicHVyIjoidmFyaWF0aW9uIn19--19f16573cafa934a908d21a80fef013aca3219fc/thinking-cat.jpg
                  signed_id: eyJfcmFpbHMiOnsiZGF0YSI6MiwiZXhwIjoiMjAyNi0wMS0xNlQxMjowMDowMC4wMDBaIiwicHVyIjoiYmxvYl9pZCJ9fQ==--e50a78b4c158cae84263a776c40322cc8b7b0b57
                  viewable_id: variant_gbHJdmfrXB
                  download_url: http://localhost:3000/rails/active_storage/blobs/redirect/eyJfcmFpbHMiOnsiZGF0YSI6MiwicHVyIjoiYmxvYl9pZCJ9fQ==--a04b7436d72914c87c4a8cbdd0574722dc35892b/thinking-cat.jpg?disposition=attachment
                  metadata: {}
                  viewable_type: variant
                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/Media"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/oauth/applications":
    get:
      summary: List connected applications
      tags:
      - OAuth
      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: applications } = await client.oauth.applications.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /oauth/applications
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Which agents and apps hold access to this store. Each one reports the
        permissions it was granted, when it was last authorized and who
        approved it, read from its live tokens.


        **Required scope:** `read_oauth_applications` (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: applications listed
          content:
            application/json:
              example:
                data:
                - id: oauthapp_UkLWZg9DAJ
                  name: Claude
                  redirect_uri: https://claude.ai/api/mcp/auth_callback
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  client_id: yrl3CseR3950JoLotpOk3IOGaDnV9-PGGtsbFDYnpHi
                  connected: false
                  scopes: []
                  last_authorized_at:
                  authorized_at:
                  authorized_by:
                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/OauthApplication"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Register an application
      tags:
      - OAuth
      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 application = await client.oauth.applications.create({
            name: 'Claude',
            redirect_uri: 'https://claude.ai/api/mcp/auth_callback',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /oauth/applications -d '{"name":"Claude","redirect_uri":"https://claude.ai/api/mcp/auth_callback"}'
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Registers a client that merchants can then connect. What the client
        may do is not set here — the merchant grants that at consent, so a
        registration carries no permissions of its own.

        Clients are public rather than confidential: a hosted connector
        cannot keep a secret, which is why PKCE is required.


        **Required scope:** `write_oauth_applications` (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: application registered
          content:
            application/json:
              example:
                id: oauthapp_UkLWZg9DAJ
                name: Claude
                redirect_uri: https://claude.ai/api/mcp/auth_callback
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                client_id: W1yx4buwyE2LcIwCdbhN-PlRaoqCVJJ5z4jOejnK3Xs
                connected: false
                scopes: []
                last_authorized_at:
                authorized_at:
                authorized_by:
              schema:
                "$ref": "#/components/schemas/OauthApplication"
        '422':
          description: the registration is not valid
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank and Redirect uri can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
                    redirect_uri:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/OauthApplicationCreateParams"
        required: true
  "/api/v3/admin/oauth/applications/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Application ID
      schema:
        type: string
    patch:
      summary: Update an application
      tags:
      - OAuth
      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 application = await client.oauth.applications.update('oap_UkLWZg9DAJ', {
            name: 'Claude Desktop',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /oauth/applications/{id} -d '{"name":"Claude Desktop"}'
      security:
      - api_key: []
        bearer_auth: []
      description: "**Required scope:** `write_oauth_applications` (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: application updated
          content:
            application/json:
              example:
                id: oauthapp_UkLWZg9DAJ
                name: Claude Desktop
                redirect_uri: https://claude.ai/api/mcp/auth_callback
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                client_id: v5e5Wm5Mu_Vzl65iOowX4FXYhFMDatM4x_bC8wbCa7V
                connected: false
                scopes: []
                last_authorized_at:
                authorized_at:
                authorized_by:
              schema:
                "$ref": "#/components/schemas/OauthApplication"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/OauthApplicationUpdateParams"
        required: true
    delete:
      summary: Remove an application
      tags:
      - OAuth
      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.oauth.applications.delete('oap_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /oauth/applications/{id}
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Takes the registration away entirely. To stop a client working
        without removing it, revoke its tokens instead.


        **Required scope:** `write_oauth_applications` (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: application removed
  "/api/v3/admin/oauth/applications/{application_id}/tokens":
    parameters:
    - name: application_id
      in: path
      required: true
      description: Application ID
      schema:
        type: string
    get:
      summary: List who is connected
      tags:
      - OAuth
      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: connections } = await client.oauth.applications.tokens.list('oap_UkLWZg9DAJ', {
            expand: ['owner'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /oauth/applications/{application_id}/tokens -d '{"expand":["owner"]}'
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        A store registers a client once and every staff member connects to
        that same registration, so this lists one entry per person who holds
        access through it. Pass `expand=owner` for who they are.


        **Required scope:** `read_oauth_applications` (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: connections listed
          content:
            application/json:
              example:
                data: []
                meta:
                  page: 1
                  limit: 25
                  count: 0
                  pages: 1
                  from: 0
                  to: 0
                  in: 0
                  previous:
                  next:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/OauthAccessToken"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/oauth/applications/{application_id}/tokens/{id}":
    parameters:
    - name: application_id
      in: path
      required: true
      description: Application ID
      schema:
        type: string
    - name: id
      in: path
      required: true
      description: Token ID
      schema:
        type: string
    delete:
      summary: Revoke one person's access
      tags:
      - OAuth
      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.oauth.applications.tokens.delete('oap_UkLWZg9DAJ', 'oat_gbHJdmfrXB')
      - lang: bash
        label: Spree CLI
        source: spree api delete /oauth/applications/{application_id}/tokens/{id}
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Cuts off one person and leaves their colleagues connected. The client
        stops working for them on its next call; the registration stays, and
        they can connect again.


        **Required scope:** `write_oauth_applications` (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: access revoked
  "/api/v3/admin/oauth/authorize":
    parameters:
    - name: client_id
      in: query
      required: true
      description: The application's client id
      schema:
        type: string
    - name: redirect_uri
      in: query
      required: true
      description: Must match what the application registered
      schema:
        type: string
    - name: response_type
      in: query
      required: true
      description: Always `code`
      schema:
        type: string
    - name: scope
      in: query
      required: false
      description: Space-delimited permission keys, the same vocabulary as API-key
        scopes
      schema:
        type: string
    - name: code_challenge
      in: query
      required: false
      description: 'PKCE challenge. Required: these clients are public'
      schema:
        type: string
    - name: code_challenge_method
      in: query
      required: false
      description: Always `S256`
      schema:
        type: string
    - name: resource
      in: query
      required: false
      description: 'RFC 8707: which protected resource the token is for'
      schema:
        type: string
    get:
      summary: Describe what a client is asking for
      tags:
      - OAuth
      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 request = await client.oauth.authorization({
            client_id: 'abc123',
            redirect_uri: 'https://claude.ai/api/mcp/auth_callback',
            response_type: 'code',
            scope: 'read_products write_orders',
            code_challenge: 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM',
            code_challenge_method: 'S256',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /oauth/authorize -d '{"client_id":"abc123","redirect_uri":"https://claude.ai/api/mcp/auth_callback","response_type":"code","scope":"read_products
          write_orders","code_challenge":"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM","code_challenge_method":"S256"}'
      security:
      - bearer_auth: []
      description: |
        What the consent screen shows the merchant: who is asking, the
        permissions the requested scopes imply, and of those, the ones this
        person can actually hand over.

        A grant only ever narrows the approver's own authority, so anything
        they do not hold themselves is not offered.
      responses:
        '200':
          description: the request described
          content:
            application/json:
              example:
                client_name: Claude
                scopes:
                - read_products
                grantable_scopes:
                - read_products
                resource: https://localhost:3000/api/v3/admin
                redirect_uri: https://claude.ai/api/mcp/auth_callback
              schema:
                type: object
                properties:
                  client_name:
                    type: string
                  scopes:
                    type: array
                    items:
                      type: string
                    description: Every permission the requested scopes imply, expanded
                  grantable_scopes:
                    type: array
                    items:
                      type: string
                    description: Of those, the ones this person may hand over
                  resource:
                    type: string
                    nullable: true
                  redirect_uri:
                    type: string
    post:
      summary: Approve a request
      tags:
      - OAuth
      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 redirect = await client.oauth.approve({
            client_id: 'abc123',
            redirect_uri: 'https://claude.ai/api/mcp/auth_callback',
            response_type: 'code',
            scope: 'read_products',
            code_challenge: 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM',
            code_challenge_method: 'S256',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /oauth/authorize -d '{"client_id":"abc123","redirect_uri":"https://claude.ai/api/mcp/auth_callback","response_type":"code","scope":"read_products","code_challenge":"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM","code_challenge_method":"S256"}'
      security:
      - bearer_auth: []
      description: |
        Records the grant and answers with where to send the browser. The
        scopes recorded are the ones this person may hand over, applied here
        rather than taken from the request — a grant is a standing ceiling,
        so one recorded too wide would widen on its own the day that person
        is promoted.
      responses:
        '200':
          description: approved
          content:
            application/json:
              example:
                redirect_uri: https://claude.ai/api/mcp/auth_callback?code=E03r-KpOOPijXr95wZcxmZf9x9ywVcSs9dLvUJHvWsU
              schema:
                type: object
                properties:
                  redirect_uri:
                    type: string
    delete:
      summary: Turn a request down
      tags:
      - OAuth
      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 redirect = await client.oauth.deny({
            client_id: 'abc123',
            redirect_uri: 'https://claude.ai/api/mcp/auth_callback',
            response_type: 'code',
            scope: 'read_products',
            code_challenge: 'E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM',
            code_challenge_method: 'S256',
          })
      - lang: bash
        label: Spree CLI
        source: spree api delete /oauth/authorize -d '{"client_id":"abc123","redirect_uri":"https://claude.ai/api/mcp/auth_callback","response_type":"code","scope":"read_products","code_challenge":"E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM","code_challenge_method":"S256"}'
      security:
      - bearer_auth: []
      description: Answers with where to send the browser, carrying the refusal.
      responses:
        '200':
          description: denied
          content:
            application/json:
              example:
                redirect_uri: https://claude.ai/api/mcp/auth_callback?error=access_denied&error_description=The+resource+owner+or+authorization+server+denied+the+request.
              schema:
                type: object
                properties:
                  redirect_uri:
                    type: string
  "/api/v3/admin/orders/{order_id}/fulfillments/{fulfillment_id}/deliveries":
    get:
      summary: List deliveries
      tags:
      - Deliveries
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The consignments of a parcel — one per tracking number, each with the carrier status last reported.

        **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: deliveries } = await client.orders.fulfillments.deliveries.list(
            'or_UkLWZg9DAJ',
            'ful_UkLWZg9DAJ',
          )

          // Each carries its own carrier status: pending, in_transit, delivered, ...
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/fulfillments/{fulfillment_id}/deliveries
      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: fulfillment_id
        in: path
        required: true
        description: Fulfillment ID
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[carrier_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `carrier` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `status` | One of `pending`, `pre_transit`, `in_transit`, `out_for_delivery`, `available_for_pickup`, `delivered`, `return_to_sender`, `failure`, `unknown` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `tracking_number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `carrier`, `created_at`, `id`, `status`, `tracking_number`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Delivery
        sortable:
        - carrier
        - created_at
        - id
        - status
        - tracking_number
        - updated_at
      responses:
        '200':
          description: deliveries found
          content:
            application/json:
              example:
                data:
                - id: dlv_UkLWZg9DAJ
                  tracking_number: U10000
                  carrier:
                  carrier_name:
                  service:
                  status: pending
                  tracking_url:
                  estimated_delivery_at:
                  delivered_at:
                  details:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  shipping_label_id:
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Record a delivery
      tags:
      - Deliveries
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds a tracked consignment to a parcel — a second box, or a freight PRO number covering several pallets. The carrier is free text.

        **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',
          })

          // A second box, or a freight consignment: the carrier is free text, so a
          // forwarder's PRO number is as valid as a parcel number.
          const delivery = await client.orders.fulfillments.deliveries.create(
            'or_UkLWZg9DAJ',
            'ful_UkLWZg9DAJ',
            { tracking_number: 'PRO-4471923', carrier: 'Estes Freight' },
          )
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{order_id}/fulfillments/{fulfillment_id}/deliveries
          -d '{"tracking_number":"PRO-4471923","carrier":"Estes Freight"}'
      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: fulfillment_id
        in: path
        required: true
        description: Fulfillment ID
        schema:
          type: string
      responses:
        '201':
          description: delivery recorded
          content:
            application/json:
              example:
                id: dlv_gbHJdmfrXB
                tracking_number: 1Z879E930346834440
                carrier: ups
                carrier_name: UPS
                service:
                status: pending
                tracking_url: https://www.ups.com/track?tracknum=1Z879E930346834440
                estimated_delivery_at:
                delivered_at:
                details:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                shipping_label_id:
        '422':
          description: tracking number already recorded on this parcel
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Tracking number has already been taken
                  details:
                    tracking_number:
                    - value: U10000
                      code: taken
                      message: has already been taken
                      specific: false
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DeliveryCreateParams"
        required: true
  "/api/v3/admin/orders/{order_id}/fulfillments/{fulfillment_id}/deliveries/{id}":
    patch:
      summary: Correct a delivery
      tags:
      - Deliveries
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Corrects the tracking number, carrier or link. A corrected number starts the carrier journey over.

        **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',
          })

          // A corrected number resets the carrier status to `pending`.
          const delivery = await client.orders.fulfillments.deliveries.update(
            'or_UkLWZg9DAJ',
            'ful_UkLWZg9DAJ',
            'dlv_UkLWZg9DAJ',
            { tracking_number: '1Z999AA10123456784', carrier: 'UPS' },
          )
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/fulfillments/{fulfillment_id}/deliveries/{id}
          -d '{"tracking_number":"1Z999AA10123456784","carrier":"UPS"}'
      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: fulfillment_id
        in: path
        required: true
        description: Fulfillment ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Delivery ID
        schema:
          type: string
      responses:
        '200':
          description: delivery updated
          content:
            application/json:
              example:
                id: dlv_UkLWZg9DAJ
                tracking_number: CORRECTED-1
                carrier:
                carrier_name:
                service:
                status: pending
                tracking_url:
                estimated_delivery_at:
                delivered_at:
                details:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                shipping_label_id:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DeliveryUpdateParams"
        required: true
    delete:
      summary: Delete a delivery
      tags:
      - Deliveries
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Removes a hand-entered consignment. One a label minted is refused — refund the label instead.

        **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',
          })

          await client.orders.fulfillments.deliveries.delete(
            'or_UkLWZg9DAJ',
            'ful_UkLWZg9DAJ',
            'dlv_UkLWZg9DAJ',
          )
      - lang: bash
        label: Spree CLI
        source: spree api delete /orders/{order_id}/fulfillments/{fulfillment_id}/deliveries/{id}
      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: fulfillment_id
        in: path
        required: true
        description: Fulfillment ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Delivery ID
        schema:
          type: string
      responses:
        '204':
          description: delivery deleted
  "/api/v3/admin/orders/{order_id}/fulfillments/{fulfillment_id}/deliveries/{id}/mark_delivered":
    patch:
      summary: Mark a delivery delivered
      tags:
      - Deliveries
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Staff confirming one consignment arrived. The parcel becomes delivered once every one of its consignments has.

        **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',
          })

          // Staff confirming one consignment arrived. The fulfillment follows once
          // every one of its consignments has.
          const delivery = await client.orders.fulfillments.deliveries.markDelivered(
            'or_UkLWZg9DAJ',
            'ful_UkLWZg9DAJ',
            'dlv_UkLWZg9DAJ',
          )
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/fulfillments/{fulfillment_id}/deliveries/{id}/mark_delivered
          -d '{ ... }'
      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: fulfillment_id
        in: path
        required: true
        description: Fulfillment ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Delivery ID
        schema:
          type: string
      responses:
        '200':
          description: delivery marked delivered
          content:
            application/json:
              example:
                id: dlv_UkLWZg9DAJ
                tracking_number: U10000
                carrier:
                carrier_name:
                service:
                status: delivered
                tracking_url:
                estimated_delivery_at:
                delivered_at: '2026-01-15T12:00:00.000Z'
                details:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                shipping_label_id:
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/DeliveryMarkDeliveredParams"
        required: true
  "/api/v3/admin/orders/{order_id}/fulfillments/{fulfillment_id}/labels":
    get:
      summary: List shipping labels
      tags:
      - Shipping Labels
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Every label bought or uploaded for a parcel, refunded ones included.

        **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: labels } = await client.orders.fulfillments.labels.list(
            'or_UkLWZg9DAJ',
            'ful_UkLWZg9DAJ',
          )
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/fulfillments/{fulfillment_id}/labels
      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: fulfillment_id
        in: path
        required: true
        description: Fulfillment ID
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[carrier_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `carrier` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `source` | One of `purchased`, `uploaded` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `status` | One of `purchased`, `refund_requested`, `refunded` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `tracking_number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `carrier`, `created_at`, `id`, `source`, `status`, `tracking_number`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: ShippingLabel
        sortable:
        - carrier
        - created_at
        - id
        - source
        - status
        - tracking_number
        - updated_at
      responses:
        '200':
          description: labels found
          content:
            application/json:
              example:
                data:
                - id: lbl_UkLWZg9DAJ
                  source: purchased
                  status: purchased
                  carrier: ups
                  carrier_name: UPS
                  service: Ground
                  tracking_number: 1Z879E930346830001
                  currency: USD
                  format: pdf
                  external_id: shp_1
                  metadata: {}
                  refunded_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  owner_id: ful_UkLWZg9DAJ
                  owner_type: fulfillment
                  cost: '7.25'
                  integration_id:
                  file_pending: false
                  download_url:
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Buy or record a shipping label
      tags:
      - Shipping Labels
      operationId: shipping_labels_purchase
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        With no body, buys the label through the parcel's carrier account. With a `file`, records a label bought elsewhere. Either way the tracking number becomes a delivery on the parcel.

        **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',
          })

          // With no body, the parcel's carrier account buys the label.
          const label = await client.orders.fulfillments.labels.create('or_UkLWZg9DAJ', 'ful_UkLWZg9DAJ')

          // The tracking number is now on the parcel's first delivery, and the label is
          // ready to print. What the merchant paid the carrier is label.display_cost.
      - lang: bash
        label: Spree CLI
        source: spree api post /orders/{order_id}/fulfillments/{fulfillment_id}/labels
          -d '{ ... }'
      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: fulfillment_id
        in: path
        required: true
        description: Fulfillment ID
        schema:
          type: string
      responses:
        '201':
          description: label purchased
          content:
            application/json:
              example:
                id: lbl_UkLWZg9DAJ
                source: purchased
                status: purchased
                carrier: ups
                carrier_name: UPS
                service: Ground
                tracking_number: 1Z879E930346834440
                currency: USD
                format: pdf
                external_id: shp_1
                metadata:
                  tracker_id: trk_1
                  file_url: https://carrier.example/label.pdf
                refunded_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                owner_id: ful_UkLWZg9DAJ
                owner_type: fulfillment
                cost: '7.25'
                integration_id:
                file_pending: true
                download_url: "/api/v3/admin/orders/or_UkLWZg9DAJ/fulfillments/ful_UkLWZg9DAJ/labels/lbl_UkLWZg9DAJ/download"
        '422':
          description: provider does not produce labels
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: This delivery method's provider does not produce labels
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ShippingLabelCreateParams"
        required: true
  "/api/v3/admin/orders/{order_id}/fulfillments/{fulfillment_id}/labels/{id}":
    get:
      summary: Get a shipping label
      tags:
      - Shipping Labels
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        One label, with what it cost and where to print it from.

        **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 label = await client.orders.fulfillments.labels.get(
            'or_UkLWZg9DAJ',
            'ful_UkLWZg9DAJ',
            'lbl_UkLWZg9DAJ',
          )
      - lang: bash
        label: Spree CLI
        source: spree api get /orders/{order_id}/fulfillments/{fulfillment_id}/labels/{id}
      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: fulfillment_id
        in: path
        required: true
        description: Fulfillment ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Shipping label ID
        schema:
          type: string
      responses:
        '200':
          description: label found
          content:
            application/json:
              example:
                id: lbl_UkLWZg9DAJ
                source: uploaded
                status: purchased
                carrier: ups
                carrier_name: UPS
                service: Ground
                tracking_number: 1Z879E930346830002
                currency: USD
                format: pdf
                external_id:
                metadata: {}
                refunded_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                owner_id: ful_UkLWZg9DAJ
                owner_type: fulfillment
                cost: '7.25'
                integration_id:
                file_pending: false
                download_url:
    delete:
      summary: Delete an uploaded label
      tags:
      - Shipping Labels
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Removes an uploaded label. A purchased label is refunded instead, so the postage history stays honest.

        **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',
          })

          // Only a label recorded from an uploaded file can be deleted; refund a bought one.
          await client.orders.fulfillments.labels.delete('or_UkLWZg9DAJ', 'ful_UkLWZg9DAJ', 'lbl_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /orders/{order_id}/fulfillments/{fulfillment_id}/labels/{id}
      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: fulfillment_id
        in: path
        required: true
        description: Fulfillment ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Shipping label ID
        schema:
          type: string
      responses:
        '204':
          description: label deleted
  "/api/v3/admin/orders/{order_id}/fulfillments/{fulfillment_id}/labels/{id}/refund":
    patch:
      summary: Refund a shipping label
      tags:
      - Shipping Labels
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Asks the carrier to refund a purchased label. The consignment it minted is removed when the parcel never shipped.

        **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 label = await client.orders.fulfillments.labels.refund(
            'or_UkLWZg9DAJ',
            'ful_UkLWZg9DAJ',
            'lbl_UkLWZg9DAJ',
          )

          // 'refunded' when the carrier settled at once, 'refund_requested' when it
          // will answer later.
          const outcome = label.status
      - lang: bash
        label: Spree CLI
        source: spree api patch /orders/{order_id}/fulfillments/{fulfillment_id}/labels/{id}/refund
          -d '{ ... }'
      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: fulfillment_id
        in: path
        required: true
        description: Fulfillment ID
        schema:
          type: string
      - name: id
        in: path
        required: true
        description: Shipping label ID
        schema:
          type: string
      responses:
        '200':
          description: refund filed
          content:
            application/json:
              example:
                id: lbl_UkLWZg9DAJ
                source: purchased
                status: refunded
                carrier: ups
                carrier_name: UPS
                service: Ground
                tracking_number: 1Z879E930346830004
                currency: USD
                format: pdf
                external_id: shp_2
                metadata: {}
                refunded_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                owner_id: ful_UkLWZg9DAJ
                owner_type: fulfillment
                cost: '7.25'
                integration_id:
                file_pending: false
                download_url:
        '422':
          description: uploaded labels cannot be refunded
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: An uploaded label was not bought through Spree and cannot
                    be refunded — delete it instead
  "/api/v3/admin/package_types":
    get:
      summary: List package types
      tags:
      - Package Types
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the store's packaging vocabulary: the box it ships parcels in
        and the cartons, pallets and containers a wholesale order leaves on.

        `volume` is the cubic meters the package occupies, converted from
        whatever unit its dimensions were recorded in — the figure freight
        volume rules compare against. It is null until all three sides are
        measured.


        **Required scope:** `read_package_types` (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: packageTypes } = await client.packageTypes.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /package_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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: sort
        in: query
        required: false
        description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`).
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `default` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `kind` | One of `box`, `envelope`, `carton`, `pallet`, `container` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `seller_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[seller_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |

          </Accordion>

          **Sort by:** `created_at`, `default`, `id`, `kind`, `name`, `seller_id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: PackageType
        sortable:
        - created_at
        - default
        - id
        - kind
        - name
        - seller_id
        - updated_at
      responses:
        '200':
          description: package types found
          content:
            application/json:
              example:
                data:
                - id: pkgtype_UkLWZg9DAJ
                  name: Master carton
                  kind: carton
                  length: '40.0'
                  width: '30.0'
                  height: '25.0'
                  weight:
                  max_weight: '20.0'
                  default: false
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  dimensions_unit: cm
                  weight_unit: kg
                  volume: '0.03'
                  seller_id:
                  seller_name:
                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/PackageType"
                  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 package type
      tags:
      - Package Types
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds a kind of packaging to the store.

        `weight` is the empty package's own weight, added to content weight on
        every quote; `max_weight` is what it can hold. Setting `default` makes
        this the box every parcel quote is built on, and demotes whichever row
        held that before.

        A variant references a `carton`-kind row to say what it is packed
        into; other kinds are the merchant's own vocabulary.


        **Required scope:** `write_package_types` (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 carton = await client.packageTypes.create({
            name: 'Master carton',
            kind: 'carton',
            length: 40,
            width: 30,
            height: 25,
            dimensions_unit: 'cm',
            max_weight: 20,
            weight_unit: 'kg',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /package_types -d '{"name":"Master carton","kind":"carton","length":40,"width":30,"height":25,"dimensions_unit":"cm","max_weight":20,"weight_unit":"kg"}'
      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: package type created
          content:
            application/json:
              example:
                id: pkgtype_gbHJdmfrXB
                name: Euro pallet
                kind: pallet
                length: '120.0'
                width: '80.0'
                height: '15.0'
                weight:
                max_weight:
                default: false
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                dimensions_unit: cm
                weight_unit: lb
                volume: '0.144'
                seller_id:
                seller_name:
              schema:
                "$ref": "#/components/schemas/PackageType"
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Kind is not included in the list
                  details:
                    kind:
                    - value: crate
                      code: inclusion
                      message: is not included in the list
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PackageTypeCreateParams"
        required: true
  "/api/v3/admin/package_types/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Package type ID
      schema:
        type: string
    get:
      summary: Get a package type
      tags:
      - Package Types
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a single package type by prefixed ID.

        **Required scope:** `read_package_types` (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 packageType = await client.packageTypes.get('pkgtype_123')
      - lang: bash
        label: Spree CLI
        source: spree api get /package_types/{id}
      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: package type found
          content:
            application/json:
              example:
                id: pkgtype_UkLWZg9DAJ
                name: Master carton
                kind: carton
                length: '40.0'
                width: '30.0'
                height: '25.0'
                weight:
                max_weight: '20.0'
                default: false
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                dimensions_unit: cm
                weight_unit: kg
                volume: '0.03'
                seller_id:
                seller_name:
              schema:
                "$ref": "#/components/schemas/PackageType"
        '404':
          description: package type not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Package type not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update a package type
      tags:
      - Package Types
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Updates a package type. Every product packed in it follows the new geometry.

        **Required scope:** `write_package_types` (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 carton = await client.packageTypes.update('pkgtype_123', {
            max_weight: 25,
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /package_types/{id} -d '{"max_weight":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
      responses:
        '200':
          description: package type updated
          content:
            application/json:
              example:
                id: pkgtype_UkLWZg9DAJ
                name: Master carton
                kind: carton
                length: '40.0'
                width: '30.0'
                height: '25.0'
                weight:
                max_weight: '25.0'
                default: false
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                dimensions_unit: cm
                weight_unit: kg
                volume: '0.03'
                seller_id:
                seller_name:
              schema:
                "$ref": "#/components/schemas/PackageType"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PackageTypeUpdateParams"
        required: true
    delete:
      summary: Delete a package type
      tags:
      - Package Types
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Removes a kind of packaging. Refused while any variant is packed into
        it — repack those products first.


        **Required scope:** `write_package_types` (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.packageTypes.delete('pkgtype_123')
      - lang: bash
        label: Spree CLI
        source: spree api delete /package_types/{id}
      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: package type deleted
  "/api/v3/admin/price_lists/{price_list_id}/products":
    get:
      summary: List price list products
      tags:
      - Price Lists
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The products the list prices, listed by name — membership is derived from the price rows.
        `expand=price_list_price` adds what the list charges for each variant, with its quantity
        breaks as tiers, the same reading a catalog's products carry.


        **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',
          })

          // `price_list_price` adds the price this list sets for each product.
          const { data: products } = await client.priceLists.products.list('pl_UkLWZg9DAJ', {
            expand: ['price_list_price'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /price_lists/{price_list_id}/products -d '{"expand":["price_list_price"]}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: price_list_id
        in: path
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches product name or variant SKU (partial, case-insensitive),
          and the store's searchable custom fields.
      - name: q[ascend_by_price]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `ascend_by_price`.
      - name: q[descend_by_price]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `descend_by_price`.
      - name: q[in_categories][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        description: Applies `in_categories` to the given value.
      - name: q[in_category]
        in: query
        required: false
        schema:
          type: string
        description: Applies `in_category` to the given value.
      - name: q[in_collection]
        in: query
        required: false
        schema:
          type: string
        description: Applies `in_collection` to the given value.
      - name: q[in_stock]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `in_stock`.
      - name: q[in_taxon]
        in: query
        required: false
        schema:
          type: string
        description: Applies `in_taxon` to the given value.
      - name: q[not_discontinued]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `not_discontinued`.
      - name: q[out_of_stock]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `out_of_stock`.
      - name: q[price_between][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: number
          minItems: 2
          maxItems: 2
        description: Applies `price_between` to the given value.
      - name: q[price_gte]
        in: query
        required: false
        schema:
          type: number
        description: Applies `price_gte` to the given value.
      - name: q[price_lte]
        in: query
        required: false
        schema:
          type: number
        description: Applies `price_lte` to the given value.
      - name: q[search_by_name]
        in: query
        required: false
        schema:
          type: string
        description: Applies `search_by_name` to the given value.
      - name: q[with_option_value_ids][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        description: Applies `with_option_value_ids` to the given value.
      - name: expand
        in: query
        required: false
        description: Comma-separated. `price_list_price` adds the resolved price to
          every row.
        example: price_list_price
        schema:
          type: string
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `available_on` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `description` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `discontinue_on` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `price` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `seller_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `slug` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `status` | One of `draft`, `active`, `archived`, `proposed`, `rejected` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[categories_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `categories_` | `automatic`, `children_count`, `created_at`, `depth`, `id`, `name`, `parent_id`, `permalink`, `position`, `pretty_name`, `products_count`, `updated_at` |
          | `categories_parent_` | `automatic`, `children_count`, `created_at`, `depth`, `id`, `name`, `parent_id`, `permalink`, `position`, `pretty_name`, `products_count`, `updated_at` |
          | `channels_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `collections_` | `automatic`, `created_at`, `id`, `name`, `permalink`, `position`, `products_count`, `sort_order`, `updated_at` |
          | `default_variant_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `default_variant_option_values_` | `created_at`, `id`, `label`, `name`, `position`, `updated_at` |
          | `default_variant_prices_` | `amount`, `compare_at_amount`, `created_at`, `currency`, `id`, `min_quantity`, `price_list_id`, `updated_at`, `variant_id` |
          | `default_variant_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `default_variant_tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |
          | `labels_` | `created_at`, `id`, `name`, `updated_at` |
          | `option_types_` | `created_at`, `id`, `kind`, `label`, `name`, `position`, `updated_at` |
          | `product_categories_` | `category_id`, `created_at`, `id`, `position`, `product_id`, `updated_at` |
          | `product_type_` | `created_at`, `id`, `name`, `updated_at` |
          | `product_type_option_types_` | `created_at`, `id`, `kind`, `label`, `name`, `position`, `updated_at` |
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `store_` | `created_at`, `id`, `name`, `updated_at` |
          | `tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `variants_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `variants_option_values_` | `created_at`, `id`, `label`, `name`, `position`, `updated_at` |
          | `variants_prices_` | `amount`, `compare_at_amount`, `created_at`, `currency`, `id`, `min_quantity`, `price_list_id`, `updated_at`, `variant_id` |
          | `variants_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `variants_tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |

          </Accordion>

          **Sort by:** `available_on`, `created_at`, `description`, `discontinue_on`, `id`, `name`, `price`, `seller_id`, `slug`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Product
        sortable:
        - available_on
        - created_at
        - description
        - discontinue_on
        - id
        - name
        - price
        - seller_id
        - slug
        - status
        - updated_at
      responses:
        '200':
          description: products found, with what the list charges
          content:
            application/json:
              example:
                data:
                - id: prod_UkLWZg9DAJ
                  name: Product 1163365
                  thumbnail_url:
                  price_list_variants:
                  - id: variant_UkLWZg9DAJ
                    label:
                    sku: SKU-137
                    currency: USD
                    source: base
                    break_count: 1
                    amount: '100.00'
                    tiers:
                    - min_quantity: 24
                      amount: '80.00'
                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/PriceListProduct"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Add products to a price list
      tags:
      - Price Lists
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds products to the list in bulk, materializing a placeholder price per variant and store currency. Already-present products are skipped.

        **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 { added_count } = await client.priceLists.products.create('pl_UkLWZg9DAJ', [
            'prod_86Rf07xd4z',
            'prod_9XbR2kQwLm',
          ])
      - lang: bash
        label: Spree CLI
        source: spree api post /price_lists/{price_list_id}/products -d '{ ... }'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: price_list_id
        in: path
        required: true
        schema:
          type: string
      responses:
        '201':
          description: products added
          content:
            application/json:
              example:
                added_count: 1
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductMembershipParams"
        required: true
    delete:
      summary: Remove products from a price list
      tags:
      - Price Lists
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Removes products from the list in bulk, hard-deleting their price rows. Ids that are not members are ignored.

        **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 { removed_count } = await client.priceLists.products.delete('pl_UkLWZg9DAJ', [
            'prod_86Rf07xd4z',
          ])
      - lang: bash
        label: Spree CLI
        source: spree api delete /price_lists/{price_list_id}/products
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: price_list_id
        in: path
        required: true
        schema:
          type: string
      responses:
        '200':
          description: products removed
          content:
            application/json:
              example:
                removed_count: 1
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductMembershipParams"
        required: true
  "/api/v3/admin/product_types":
    get:
      summary: List product types
      tags:
      - Product Types
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a paginated list of product types.

        A product type is a back-office template: it seeds option types and
        categories onto products created with it, and defines which custom
        fields those products' forms show. It is not exposed on the Store API.


        **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: productTypes } = await client.productTypes.list({ name_cont: 'shirt' })
      - lang: bash
        label: Spree CLI
        source: spree api get /product_types -d '{"name_cont":"shirt"}'
      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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[option_types_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `option_types_` | `created_at`, `id`, `kind`, `label`, `name`, `position`, `updated_at` |

          </Accordion>

          **Sort by:** `created_at`, `id`, `name`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: ProductType
        sortable:
        - created_at
        - id
        - name
        - updated_at
      responses:
        '200':
          description: product types found
          content:
            application/json:
              example:
                data:
                - id: pt_UkLWZg9DAJ
                  name: T-Shirt
                  products_count: 0
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  delivery_profile_id:
                  option_type_ids: []
                  category_ids: []
                  custom_field_definitions: []
                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/ProductType"
                  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 type
      tags:
      - Product Types
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Creates a product type.

        `option_type_ids` and `category_ids` seed products created with this
        type. `custom_field_definitions` is a replace-set of the definitions the
        product form renders, in `sort_order`. `required` is advisory — the
        dashboard marks the field, but a blank value is never rejected.


        **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',
          })

          // Products created with this type start with its option types and categories.
          const productType = await client.productTypes.create({
            name: 'Hoodie',
            option_type_ids: ['opt_UkLWZg9DAJ'],
            category_ids: ['ctg_UkLWZg9DAJ'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /product_types -d '{"name":"Hoodie","option_type_ids":["opt_UkLWZg9DAJ"],"category_ids":["ctg_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:
        '201':
          description: product type created
          content:
            application/json:
              example:
                id: pt_gbHJdmfrXB
                name: Hoodie
                products_count: 0
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivery_profile_id:
                option_type_ids: []
                category_ids: []
                custom_field_definitions: []
              schema:
                "$ref": "#/components/schemas/ProductType"
        '422':
          description: unprocessable entity
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductTypeCreateParams"
        required: true
  "/api/v3/admin/product_types/{id}":
    parameters:
    - name: id
      in: path
      description: Product type ID
      required: true
      schema:
        type: string
    get:
      summary: Retrieve a product type
      tags:
      - Product Types
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a single product type with its option types, categories and custom fields.

        **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 productType = await client.productTypes.get('pt_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /product_types/{id}
      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: product type found
          content:
            application/json:
              example:
                id: pt_UkLWZg9DAJ
                name: T-Shirt
                products_count: 0
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivery_profile_id:
                option_type_ids: []
                category_ids: []
                custom_field_definitions: []
              schema:
                "$ref": "#/components/schemas/ProductType"
        '404':
          description: product type not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Product type not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update a product type
      tags:
      - Product Types
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Updates a product type.

        Changes never modify products that already carry the type — use
        `apply_to_products` to backfill those.


        **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 productType = await client.productTypes.update('pt_UkLWZg9DAJ', {
            name: 'Premium T-Shirt',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /product_types/{id} -d '{"name":"Premium T-Shirt"}'
      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: product type updated
          content:
            application/json:
              example:
                id: pt_UkLWZg9DAJ
                name: Premium T-Shirt
                products_count: 0
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                delivery_profile_id:
                option_type_ids: []
                category_ids: []
                custom_field_definitions: []
              schema:
                "$ref": "#/components/schemas/ProductType"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ProductTypeUpdateParams"
        required: true
    delete:
      summary: Delete a product type
      tags:
      - Product Types
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Deletes a product type. Types still used by products cannot be deleted.

        **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.productTypes.delete('pt_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /product_types/{id}
      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: product type deleted
  "/api/v3/admin/product_types/{id}/apply_to_products":
    parameters:
    - name: id
      in: path
      description: Product type ID
      required: true
      schema:
        type: string
    post:
      summary: Apply a product type to its existing products
      tags:
      - Product Types
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Backfills the type's option types and categories onto the products that
        already carry it. Additive and idempotent — nothing is removed, and
        re-running is safe.

        Runs in the background; the response reports how many products the type
        currently has.


        **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',
          })

          // Backfills the type's option types and categories onto products that already have it.
          const result = await client.productTypes.applyToProducts('pt_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api post /product_types/{id}/apply_to_products -d '{ ... }'
      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:
        '202':
          description: backfill accepted
          content:
            application/json:
              example:
                products_count: 0
              schema:
                type: object
                properties:
                  products_count:
                    type: integer
  "/api/v3/admin/purchase_orders":
    get:
      summary: List purchase orders
      tags:
      - Purchase Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Stock bought from suppliers. A purchase order carries what a purchase
        has and a stock transfer does not: a supplier, a unit cost per line and
        an expected arrival date.

        Ordered units never count toward availability. Nothing here changes
        `count_on_hand` until `receive` runs, because a merchant who has
        ordered stock does not have it.

        Statuses are `draft`, `ordered`, `partially_received`, `received`, `over_received` and
        `canceled`. Each move between them is its own endpoint, not a `PATCH`
        that writes `status`.

        Filter with Ransack predicates such as `q[status_eq]`,
        `q[supplier_id_eq]` or `q[expected_at_lteq]`. Expand `items`,
        `supplier` and `destination_location`.


        **Required scope:** `read_purchasing` (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: purchaseOrders } = await client.purchaseOrders.list({
            status_eq: 'ordered',
            expand: ['supplier'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /purchase_orders -d '{"status_eq":"ordered","expand":["supplier"]}'
      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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of number and reference (partial, case-insensitive).
      - name: q[closed]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `closed`.
      - name: q[open]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `open`.
      - name: q[overdue]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `overdue`.
      - name: q[past_cancel_by]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `past_cancel_by`.
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: expand
        in: query
        required: false
        description: 'Comma-separated associations to embed: items, supplier, destination_location'
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `cancel_by` | Date | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `closed_short_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `currency` | One of the `CurrencyCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `destination_location_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `expected_at` | Date | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `ordered_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `received_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `reference` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `status` | One of `draft`, `ordered`, `partially_received`, `received`, `over_received`, `canceled` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `supplier_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[destination_location_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `destination_location_` | `active`, `country_code`, `created_at`, `default`, `id`, `kind`, `name`, `pickup_enabled`, `returns_enabled`, `seller_id`, `state_code`, `updated_at` |
          | `destination_location_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `items_` | `created_at`, `id`, `quantity_ordered`, `quantity_received`, `quantity_rejected`, `unit_cost`, `updated_at`, `variant_id` |
          | `items_variant_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `supplier_` | `city`, `contact_name`, `country_code`, `created_at`, `email`, `id`, `name`, `phone`, `updated_at` |

          </Accordion>

          **Sort by:** `cancel_by`, `closed_short_at`, `created_at`, `currency`, `destination_location_id`, `expected_at`, `id`, `number`, `ordered_at`, `received_at`, `reference`, `status`, `supplier_id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: PurchaseOrder
        sortable:
        - cancel_by
        - closed_short_at
        - created_at
        - currency
        - destination_location_id
        - expected_at
        - id
        - number
        - ordered_at
        - received_at
        - reference
        - status
        - supplier_id
        - updated_at
      responses:
        '200':
          description: purchase orders found
          content:
            application/json:
              example:
                data:
                - id: po_UkLWZg9DAJ
                  number: PO1001
                  status: draft
                  currency: USD
                  reference:
                  notes:
                  metadata: {}
                  close_reason:
                  items_count: 1
                  quantity_received_total: 0
                  quantity_rejected_total: 0
                  ordered_at:
                  received_at:
                  closed_short_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  expected_at: '2026-10-01'
                  cancel_by:
                  closed_short: false
                  quantity_ordered_total: 100
                  editable: true
                  subtotal: '1250.00'
                  supplier_id: sup_UkLWZg9DAJ
                  destination_location_id: sloc_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/PurchaseOrder"
                  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 purchase order
      tags:
      - Purchase Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Drafts an order. Nothing is on order and nothing touches availability
        until the order is marked as ordered and then received.

        `currency` defaults to the store's; set it for a foreign-currency
        order. `expected_at` is a calendar date (`yyyy-mm-dd`) — the day the
        supplier promised means the same day in every timezone.


        **Required scope:** `write_purchasing` (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 purchaseOrder = await client.purchaseOrders.create({
            supplier_id: 'sup_1234567890',
            destination_location_id: 'sloc_1234567890',
            expected_at: '2026-10-01',
            items: [{ variant_id: 'variant_1234567890', quantity_ordered: 100, unit_cost: '12.50' }],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /purchase_orders -d '{"supplier_id":"sup_1234567890","destination_location_id":"sloc_1234567890","expected_at":"2026-10-01","items":[{"variant_id":"variant_1234567890","quantity_ordered":100,"unit_cost":"12.50"}]}'
      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: purchase order created
          content:
            application/json:
              example:
                id: po_gbHJdmfrXB
                number: PO1002
                status: draft
                currency: USD
                reference: SUP-8891
                notes:
                metadata: {}
                close_reason:
                items_count: 1
                quantity_received_total: 0
                quantity_rejected_total: 0
                ordered_at:
                received_at:
                closed_short_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                expected_at: '2026-10-01'
                cancel_by:
                closed_short: false
                quantity_ordered_total: 100
                editable: true
                subtotal: '1250.00'
                supplier_id: sup_UkLWZg9DAJ
                destination_location_id: sloc_UkLWZg9DAJ
              schema:
                "$ref": "#/components/schemas/PurchaseOrder"
        '404':
          description: supplier belongs to another store
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Supplier not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PurchaseOrderCreateParams"
        required: true
  "/api/v3/admin/purchase_orders/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Purchase order ID
      schema:
        type: string
    get:
      summary: Get a purchase order
      tags:
      - Purchase Orders
      security:
      - api_key: []
        bearer_auth: []
      description: "**Required scope:** `read_purchasing` (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 purchaseOrder = await client.purchaseOrders.get('po_1234567890', {
            expand: ['items', 'supplier'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /purchase_orders/{id} -d '{"expand":["items","supplier"]}'
      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: expand
        in: query
        required: false
        description: 'Comma-separated associations to embed: items, supplier, destination_location'
        schema:
          type: string
      responses:
        '200':
          description: purchase order found
          content:
            application/json:
              example:
                id: po_UkLWZg9DAJ
                number: PO1001
                status: draft
                currency: USD
                reference:
                notes:
                metadata: {}
                close_reason:
                items_count: 1
                quantity_received_total: 0
                quantity_rejected_total: 0
                ordered_at:
                received_at:
                closed_short_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                expected_at: '2026-10-01'
                cancel_by:
                closed_short: false
                quantity_ordered_total: 100
                editable: true
                subtotal: '1250.00'
                supplier_id: sup_UkLWZg9DAJ
                destination_location_id: sloc_UkLWZg9DAJ
                items:
                - id: poi_UkLWZg9DAJ
                  quantity_ordered: 100
                  quantity_received: 0
                  quantity_rejected: 0
                  quantity_over: 0
                  outstanding: 100
                  currency: USD
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  unit_cost: '12.50'
                  total_cost: '1250.00'
                  purchase_order_id: po_UkLWZg9DAJ
                  variant_id: variant_gbHJdmfrXB
                  product_id: prod_UkLWZg9DAJ
                  variant_name: Product 1849018
                  variant_sku: SKU-221
                  options_text: 'Size: S'
                  thumbnail_url:
                supplier:
                  id: sup_UkLWZg9DAJ
                  name: Acme Wholesale
                  contact_name: Dana Okafor
                  email: supplier7@example.com
                  phone: 555-0100
                  notes:
                  address1:
                  address2:
                  city:
                  state_name:
                  state_code:
                  country_code:
                  postal_code:
                  purchase_orders_count: 1
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  deleted_at:
                  can_be_deleted: false
              schema:
                "$ref": "#/components/schemas/PurchaseOrder"
        '404':
          description: purchase order not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Purchase order not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update a purchase order
      tags:
      - Purchase Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Edits a draft: its supplier, destination, dates, reference, notes and
        lines. Sending `items` replaces every line the order holds. Status
        moves through the order's own actions, never through this endpoint.


        **Required scope:** `write_purchasing` (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',
          })

          // Drafts only. Sending `items` replaces every line on the order.
          const purchaseOrder = await client.purchaseOrders.update('po_1234567890', {
            expected_at: '2026-10-15',
            reference: 'ACME-88412',
            items: [{ variant_id: 'variant_1234567890', quantity_ordered: 120, unit_cost: '12.50' }],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /purchase_orders/{id} -d '{"expected_at":"2026-10-15","reference":"ACME-88412","items":[{"variant_id":"variant_1234567890","quantity_ordered":120,"unit_cost":"12.50"}]}'
      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: purchase order updated
          content:
            application/json:
              example:
                id: po_UkLWZg9DAJ
                number: PO1001
                status: draft
                currency: USD
                reference: ACME-4471
                notes:
                metadata: {}
                close_reason:
                items_count: 1
                quantity_received_total: 0
                quantity_rejected_total: 0
                ordered_at:
                received_at:
                closed_short_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                expected_at: '2026-10-15'
                cancel_by:
                closed_short: false
                quantity_ordered_total: 120
                editable: true
                subtotal: '1410.00'
                supplier_id: sup_UkLWZg9DAJ
                destination_location_id: sloc_UkLWZg9DAJ
              schema:
                "$ref": "#/components/schemas/PurchaseOrder"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PurchaseOrderUpdateParams"
        required: true
  "/api/v3/admin/purchase_orders/{id}/mark_ordered":
    parameters:
    - name: id
      in: path
      required: true
      description: Purchase order ID
      schema:
        type: string
    patch:
      summary: Place the order with the supplier
      tags:
      - Purchase Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Moves a `draft` to `ordered`: the lines are frozen and `ordered_at` is
        stamped. Availability is still untouched — ordered stock is not stock
        the merchant has.


        **Required scope:** `write_purchasing` (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',
          })

          // Sends the order to the supplier: the lines freeze and the expected date starts counting.
          const purchaseOrder = await client.purchaseOrders.markOrdered('po_1234567890')
      - lang: bash
        label: Spree CLI
        source: spree api patch /purchase_orders/{id}/mark_ordered -d '{ ... }'
      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: purchase order placed
          content:
            application/json:
              example:
                id: po_UkLWZg9DAJ
                number: PO1001
                status: ordered
                currency: USD
                reference:
                notes:
                metadata: {}
                close_reason:
                items_count: 1
                quantity_received_total: 0
                quantity_rejected_total: 0
                ordered_at: '2026-01-15T12:00:00.000Z'
                received_at:
                closed_short_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                expected_at: '2026-10-01'
                cancel_by:
                closed_short: false
                quantity_ordered_total: 100
                editable: false
                subtotal: '1250.00'
                supplier_id: sup_UkLWZg9DAJ
                destination_location_id: sloc_UkLWZg9DAJ
              schema:
                "$ref": "#/components/schemas/PurchaseOrder"
  "/api/v3/admin/purchase_orders/{purchase_order_id}/stock_receipts":
    parameters:
    - name: purchase_order_id
      in: path
      required: true
      description: Purchase order ID
      schema:
        type: string
    get:
      summary: List the deliveries booked against an order
      tags:
      - Purchase Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Each delivery the dock counted in, newest first — with its packing-slip reference and what it accepted and refused.

        **Required scope:** `read_purchasing` (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',
          })

          // Every delivery booked against the order, with its lines.
          const { data: stockReceipts } = await client.purchaseOrders.stockReceipts.list('po_1234567890', {
            expand: ['items'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /purchase_orders/{purchase_order_id}/stock_receipts
          -d '{"expand":["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: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `receivable_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `receivable_type` | Type | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `received_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `received_by_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `received_by_type` | Type | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `reference` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `number`, `receivable_id`, `receivable_type`, `received_at`, `received_by_id`, `received_by_type`, `reference`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: StockReceipt
        sortable:
        - created_at
        - id
        - number
        - receivable_id
        - receivable_type
        - received_at
        - received_by_id
        - received_by_type
        - reference
        - updated_at
      responses:
        '200':
          description: deliveries found
          content:
            application/json:
              example:
                data:
                - id: sr_UkLWZg9DAJ
                  number: SR1001
                  reference: DN-4471
                  notes:
                  metadata: {}
                  quantity_accepted_total: 60
                  quantity_rejected_total: 0
                  received_at: '2026-01-15T12:00:00.000Z'
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  receivable_type: purchase_order
                  receivable_id: po_UkLWZg9DAJ
                  received_by_id:
                  received_by_type:
                  items_count: 1
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Book in a delivery
      tags:
      - Purchase Orders
      operationId: purchase_orders_receive
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The moment purchased goods first count toward availability. Records
        one delivery as a stock receipt: what this delivery brought, per line,
        not a running total — a second delivery adds to the first.

        `quantity_accepted` reaches the shelf; `quantity_rejected` is refused
        and recorded with a `rejection_reason` (`damaged`, `wrong_item`,
        `expired` or `other`), never stocked. Omit `items` to book in
        everything still outstanding, intact.

        Each `received` stock movement carries the line's `unit_cost` and
        names the receipt, so a delivery can be reconciled against the ledger.

        The order stays `partially_received` while any line is still owed,
        settles in `received` once every line has what it expected, and in
        `over_received` once any line has more.


        **Required scope:** `write_purchasing` (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',
          })

          // This delivery's counts, not running totals: 58 accepted, 2 refused as
          // damaged. A second delivery adds to the first. Omit `items` to book in
          // everything still outstanding, intact.
          const stockReceipt = await client.purchaseOrders.stockReceipts.create('po_1234567890', {
            reference: 'DN-4471',
            items: [
              {
                id: 'poi_1234567890',
                quantity_accepted: 58,
                quantity_rejected: 2,
                rejection_reason: 'damaged',
              },
            ],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /purchase_orders/{purchase_order_id}/stock_receipts
          -d '{"reference":"DN-4471","items":[{"id":"poi_1234567890","quantity_accepted":58,"quantity_rejected":2,"rejection_reason":"damaged"}]}'
      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: delivery booked in
          content:
            application/json:
              example:
                id: sr_UkLWZg9DAJ
                number: SR1001
                reference: DN-4471
                notes:
                metadata: {}
                quantity_accepted_total: 58
                quantity_rejected_total: 2
                received_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                receivable_type: purchase_order
                receivable_id: po_UkLWZg9DAJ
                received_by_id: adm_UkLWZg9DAJ
                received_by_type: admin_user
                items_count: 1
              schema:
                "$ref": "#/components/schemas/StockReceipt"
        '422':
          description: order has not been placed yet
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: Only a purchase order that has been placed can be received
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/StockReceiptCreateParams"
        required: true
  "/api/v3/admin/purchase_orders/{id}/mark_draft":
    parameters:
    - name: id
      in: path
      required: true
      description: Purchase order ID
      schema:
        type: string
    patch:
      summary: Take an order back to draft
      tags:
      - Purchase Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Reopens a placed order for editing. Only while no delivery has been booked against it; `ordered_at` is cleared.

        **Required scope:** `write_purchasing` (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',
          })

          // Only while no delivery has been booked against it.
          const purchaseOrder = await client.purchaseOrders.markDraft('po_1234567890')
      - lang: bash
        label: Spree CLI
        source: spree api patch /purchase_orders/{id}/mark_draft -d '{ ... }'
      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: order back in draft
          content:
            application/json:
              example:
                id: po_UkLWZg9DAJ
                number: PO1001
                status: draft
                currency: USD
                reference:
                notes:
                metadata: {}
                close_reason:
                items_count: 1
                quantity_received_total: 0
                quantity_rejected_total: 0
                ordered_at:
                received_at:
                closed_short_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                expected_at: '2026-10-01'
                cancel_by:
                closed_short: false
                quantity_ordered_total: 100
                editable: true
                subtotal: '1250.00'
                supplier_id: sup_UkLWZg9DAJ
                destination_location_id: sloc_UkLWZg9DAJ
              schema:
                "$ref": "#/components/schemas/PurchaseOrder"
  "/api/v3/admin/purchase_orders/{id}/close":
    parameters:
    - name: id
      in: path
      required: true
      description: Purchase order ID
      schema:
        type: string
    patch:
      summary: Close an order short
      tags:
      - Purchase Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Ends a partially received order whose balance the supplier will not
        deliver. Nothing moves: what arrived stays on the shelf, the
        outstanding count stays on each line, and the order settles in
        `received` with `closed_short_at` and the `reason` recorded.


        **Required scope:** `write_purchasing` (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',
          })

          // The supplier will not send the balance: keep what arrived, record why.
          const purchaseOrder = await client.purchaseOrders.close('po_1234567890', {
            reason: 'Supplier out of stock',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /purchase_orders/{id}/close -d '{"reason":"Supplier
          out of stock"}'
      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: order closed short
          content:
            application/json:
              example:
                id: po_UkLWZg9DAJ
                number: PO1001
                status: received
                currency: USD
                reference:
                notes:
                metadata: {}
                close_reason: Supplier out of stock
                items_count: 1
                quantity_received_total: 60
                quantity_rejected_total: 0
                ordered_at: '2026-01-15T12:00:00.000Z'
                received_at: '2026-01-15T12:00:00.000Z'
                closed_short_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                expected_at: '2026-10-01'
                cancel_by:
                closed_short: true
                quantity_ordered_total: 100
                editable: false
                subtotal: '1250.00'
                supplier_id: sup_UkLWZg9DAJ
                destination_location_id: sloc_UkLWZg9DAJ
              schema:
                "$ref": "#/components/schemas/PurchaseOrder"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReceivableCloseParams"
        required: true
  "/api/v3/admin/purchase_orders/{id}/cancel":
    parameters:
    - name: id
      in: path
      required: true
      description: Purchase order ID
      schema:
        type: string
    patch:
      summary: Cancel a purchase order
      tags:
      - Purchase Orders
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Closes what is still outstanding. Nothing is unwound: a purchase order
        never moved stock until units were received, and units already received
        stay on the shelf because the merchant has them.

        A `reason` is appended to the order's notes.


        **Required scope:** `write_purchasing` (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 purchaseOrder = await client.purchaseOrders.cancel('po_1234567890', {
            reason: 'Supplier discontinued the line',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /purchase_orders/{id}/cancel -d '{"reason":"Supplier
          discontinued the line"}'
      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: purchase order cancelled
          content:
            application/json:
              example:
                id: po_UkLWZg9DAJ
                number: PO1001
                status: canceled
                currency: USD
                reference:
                notes: Supplier went under
                metadata: {}
                close_reason:
                items_count: 1
                quantity_received_total: 0
                quantity_rejected_total: 0
                ordered_at:
                received_at:
                closed_short_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                expected_at: '2026-10-01'
                cancel_by:
                closed_short: false
                quantity_ordered_total: 100
                editable: false
                subtotal: '1250.00'
                supplier_id: sup_UkLWZg9DAJ
                destination_location_id: sloc_UkLWZg9DAJ
              schema:
                "$ref": "#/components/schemas/PurchaseOrder"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/PurchaseOrderCancelParams"
        required: true
  "/api/v3/admin/reporting/saved_reports":
    get:
      summary: List saved reports
      tags:
      - Reports
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the store's saved reports, each a named query staff can run again.

        **Required scope:** `read_reports` (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: savedReports } = await client.reporting.savedReports.list()
      - lang: bash
        label: Spree CLI
        source: spree api get /reporting/saved_reports
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `seeded` | True or false | `eq` `not_eq` `in` `not_in` `true` `false` `null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `name`, `seeded`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: SavedReport
        sortable:
        - created_at
        - id
        - name
        - seeded
        - updated_at
      responses:
        '200':
          description: saved reports found
          content:
            application/json:
              example:
                data:
                - id: sq_UkLWZg9DAJ
                  name: Sales by channel
                  description:
                  query:
                    metrics:
                    - total_sales
                    - orders
                    dimensions:
                    - channel
                  seeded: false
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  user_id:
                  author_name:
                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/SavedReport"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
    post:
      summary: Create a saved report
      tags:
      - Reports
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Saves a reporting query under a name so staff can run it again. The query is validated against the reporting registry.

        **Required scope:** `write_reports` (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 savedReport = await client.reporting.savedReports.create({
            name: 'Orders by channel',
            description: 'Weekly review',
            query: { metrics: ['total_sales', 'orders'], dimensions: ['channel'] },
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /reporting/saved_reports -d '{"name":"Orders by channel","description":"Weekly
          review","query":{"metrics":["total_sales","orders"],"dimensions":["channel"]}}'
      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: saved report created
          content:
            application/json:
              example:
                id: sq_gbHJdmfrXB
                name: Orders by channel
                description: Weekly review
                query:
                  metrics:
                  - total_sales
                  - orders
                  dimensions:
                  - channel
                seeded: false
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                user_id: adm_UkLWZg9DAJ
                author_name: Renae Rath
              schema:
                "$ref": "#/components/schemas/SavedReport"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SavedReportCreateParams"
        required: true
  "/api/v3/admin/reporting/saved_reports/{id}":
    parameters:
    - name: id
      in: path
      description: Saved report ID
      required: true
      schema:
        type: string
    patch:
      summary: Update a saved report
      tags:
      - Reports
      security:
      - api_key: []
        bearer_auth: []
      description: "**Required scope:** `write_reports` (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 savedReport = await client.reporting.savedReports.update('sq_UkLWZg9DAJ', {
            name: 'Sales by channel (monthly)',
            description: 'For the board pack',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /reporting/saved_reports/{id} -d '{"name":"Sales by
          channel (monthly)","description":"For the board pack"}'
      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: saved report updated
          content:
            application/json:
              example:
                id: sq_UkLWZg9DAJ
                name: Sales by channel (monthly)
                description: For the board pack
                query:
                  metrics:
                  - total_sales
                  - orders
                  dimensions:
                  - channel
                seeded: false
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                user_id:
                author_name:
              schema:
                "$ref": "#/components/schemas/SavedReport"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SavedReportUpdateParams"
        required: true
  "/api/v3/admin/reporting/query":
    post:
      summary: Run a reporting query
      tags:
      - Reports
      x-spree-agent: false
      x-spree-agent-reason: query_report runs this query, with describe_reporting
        to learn the vocabulary first.
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Runs a query against the store's registered metrics and dimensions, in
        the store's time zone. A metric or dimension the registry does not know
        is refused with the names that are valid, and an API key needs the read
        scope of every resource the query touches.


        **Required scope:** `read_reports` (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.reporting.query({
            metrics: ['total_sales', 'orders'],
            dimensions: [{ name: 'completed_at', grain: 'day' }],
            time_range: { preset: 'last_7_days' },
            compare: 'previous_period',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /reporting/query -d '{"metrics":["total_sales","orders"],"dimensions":[{"name":"completed_at","grain":"day"}],"time_range":{"preset":"last_7_days"},"compare":"previous_period"}'
      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: query results
          content:
            application/json:
              example:
                meta:
                  currency: USD
                  time_range:
                    since: '2026-01-08T00:00:00Z'
                    until: '2026-01-15T23:59:59Z'
                  previous_time_range:
                    since: '2025-12-31T00:00:00Z'
                    until: '2026-01-07T23:59:59Z'
                  metrics:
                  - total_sales
                  - orders
                  dimensions:
                  - name: completed_at
                    grain: day
                totals:
                  total_sales:
                    value: '110.00'
                    previous: '0.00'
                    growth:
                    display: "$110.00"
                  orders:
                    value: 1
                    previous: 0
                    growth:
                rows:
                - dimensions:
                    completed_at: '2026-01-08'
                  metrics:
                    total_sales:
                      value: '0.00'
                      previous: '0.00'
                      growth: '0'
                      display: "$0.00"
                    orders:
                      value: 0
                      previous: 0
                      growth: '0'
                - dimensions:
                    completed_at: '2026-01-09'
                  metrics:
                    total_sales:
                      value: '0.00'
                      previous: '0.00'
                      growth: '0'
                      display: "$0.00"
                    orders:
                      value: 0
                      previous: 0
                      growth: '0'
                - dimensions:
                    completed_at: '2026-01-10'
                  metrics:
                    total_sales:
                      value: '0.00'
                      previous: '0.00'
                      growth: '0'
                      display: "$0.00"
                    orders:
                      value: 0
                      previous: 0
                      growth: '0'
                - dimensions:
                    completed_at: '2026-01-11'
                  metrics:
                    total_sales:
                      value: '0.00'
                      previous: '0.00'
                      growth: '0'
                      display: "$0.00"
                    orders:
                      value: 0
                      previous: 0
                      growth: '0'
                - dimensions:
                    completed_at: '2026-01-12'
                  metrics:
                    total_sales:
                      value: '0.00'
                      previous: '0.00'
                      growth: '0'
                      display: "$0.00"
                    orders:
                      value: 0
                      previous: 0
                      growth: '0'
                - dimensions:
                    completed_at: '2026-01-13'
                  metrics:
                    total_sales:
                      value: '110.00'
                      previous: '0.00'
                      growth:
                      display: "$110.00"
                    orders:
                      value: 1
                      previous: 0
                      growth:
                - dimensions:
                    completed_at: '2026-01-14'
                  metrics:
                    total_sales:
                      value: '0.00'
                      previous: '0.00'
                      growth: '0'
                      display: "$0.00"
                    orders:
                      value: 0
                      previous: 0
                      growth: '0'
                - dimensions:
                    completed_at: '2026-01-15'
                  metrics:
                    total_sales:
                      value: '0.00'
                      previous: '0.00'
                      growth: '0'
                      display: "$0.00"
                    orders:
                      value: 0
                      previous: 0
                      growth: '0'
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReportingQueryParams"
        required: true
  "/api/v3/admin/sellers/{seller_id}/requirement_submissions":
    parameters:
    - name: seller_id
      in: path
      required: true
      description: Seller prefixed ID
      schema:
        type: string
    post:
      summary: Waive a requirement for a seller
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Excuses this one seller from a requirement the marketplace asks of
        everyone, recorded as a `waived` submission. The operator never
        submits on the seller's behalf: this endpoint only waives.


        **Required scope:** `write_sellers` (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: requirement waived
          content:
            application/json:
              example:
                id: selsub_UkLWZg9DAJ
                status: waived
                note:
                review_note: Verified offline
                reference:
                metadata: {}
                reviewed_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                seller_id: sel_UkLWZg9DAJ
                requirement_id: selreq_UkLWZg9DAJ
                requirement_name: VAT number check
                file_url:
                file_name:
              schema:
                "$ref": "#/components/schemas/SellerRequirementSubmission"
        '404':
          description: the requirement belongs to another store
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Seller requirement not found
      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',
          })

          // Excuses this seller from a requirement every other seller still has to meet.
          const submission = await client.sellers.requirementSubmissions.waive('sel_UkLWZg9DAJ', {
            requirement_id: 'selreq_UkLWZg9DAJ',
            review_note: 'Registered charity, exempt from the business licence check.',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /sellers/{seller_id}/requirement_submissions -d '{"requirement_id":"selreq_UkLWZg9DAJ","review_note":"Registered
          charity, exempt from the business licence check."}'
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SellerRequirementWaiveParams"
        required: true
    get:
      summary: List a seller's requirement submissions
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        What this seller submitted against the marketplace requirements, with the review decision on each.

        **Required scope:** `read_sellers` (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: submissions } = await client.sellers.requirementSubmissions.list('sel_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /sellers/{seller_id}/requirement_submissions
      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
        description: Page number
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        description: Records per page (max 100)
        schema:
          type: integer
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `reviewed_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `status` | One of `pending`, `accepted`, `rejected`, `waived` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[requirement_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `requirement_` | `created_at`, `id`, `name`, `position`, `updated_at` |
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |

          </Accordion>

          **Sort by:** `created_at`, `id`, `reviewed_at`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: SellerRequirementSubmission
        sortable:
        - created_at
        - id
        - reviewed_at
        - status
        - updated_at
      responses:
        '200':
          description: submissions listed
          content:
            application/json:
              example:
                data:
                - id: selsub_UkLWZg9DAJ
                  status: pending
                  note:
                  review_note:
                  reference:
                  metadata: {}
                  reviewed_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  seller_id: sel_UkLWZg9DAJ
                  requirement_id: selreq_UkLWZg9DAJ
                  requirement_name: Confirm something 5
                  file_url:
                  file_name:
                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/SellerRequirementSubmission"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/sellers/{seller_id}/requirement_submissions/{id}/accept":
    parameters:
    - name: seller_id
      in: path
      required: true
      description: Seller prefixed ID
      schema:
        type: string
    - name: id
      in: path
      required: true
      description: Requirement submission ID
      schema:
        type: string
    patch:
      summary: Accept a seller's submission
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Marks what the seller submitted as meeting the requirement.

        **Required scope:** `write_sellers` (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: submission accepted
          content:
            application/json:
              example:
                id: selsub_UkLWZg9DAJ
                status: accepted
                note:
                review_note: VAT number verified
                reference:
                metadata: {}
                reviewed_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                seller_id: sel_UkLWZg9DAJ
                requirement_id: selreq_UkLWZg9DAJ
                requirement_name: VAT number check
                file_url:
                file_name:
              schema:
                "$ref": "#/components/schemas/SellerRequirementSubmission"
      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 submission = await client.sellers.requirementSubmissions.accept(
            'sel_UkLWZg9DAJ',
            'selsub_UkLWZg9DAJ',
            { review_note: 'Licence verified with the issuing authority.' },
          )
      - lang: bash
        label: Spree CLI
        source: spree api patch /sellers/{seller_id}/requirement_submissions/{id}/accept
          -d '{"review_note":"Licence verified with the issuing authority."}'
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SellerRequirementReviewParams"
  "/api/v3/admin/sellers/{seller_id}/requirement_submissions/{id}/reject":
    parameters:
    - name: seller_id
      in: path
      required: true
      description: Seller prefixed ID
      schema:
        type: string
    - name: id
      in: path
      required: true
      description: Requirement submission ID
      schema:
        type: string
    patch:
      summary: Reject a seller's submission
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Turns down what the seller submitted. `review_note` is the reason sent
        back to the seller, who can then submit again.


        **Required scope:** `write_sellers` (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: submission rejected
          content:
            application/json:
              example:
                id: selsub_UkLWZg9DAJ
                status: rejected
                note:
                review_note: The VAT number does not match the company name
                reference:
                metadata: {}
                reviewed_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                seller_id: sel_UkLWZg9DAJ
                requirement_id: selreq_UkLWZg9DAJ
                requirement_name: VAT number check
                file_url:
                file_name:
              schema:
                "$ref": "#/components/schemas/SellerRequirementSubmission"
      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 review note is sent back to the seller as the reason.
          const submission = await client.sellers.requirementSubmissions.reject(
            'sel_UkLWZg9DAJ',
            'selsub_UkLWZg9DAJ',
            { review_note: 'The document has expired. Please upload a current one.' },
          )
      - lang: bash
        label: Spree CLI
        source: spree api patch /sellers/{seller_id}/requirement_submissions/{id}/reject
          -d '{"review_note":"The document has expired. Please upload a current one."}'
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SellerRequirementReviewParams"
  "/api/v3/admin/seller_requirements":
    get:
      summary: List seller requirements
      tags:
      - Seller Requirements
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        What this marketplace asks of a seller before it will let them trade,
        in the order sellers work through it.

        Each row is one configured requirement. `required` says whether it
        stands between the seller and approval — the others are shown as
        recommended and counted in their progress, but never block. `active`
        switches one off without losing how it was worded.


        **Required scope:** `read_sellers` (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',
          })

          // The checklist in the order sellers work through it. `required` items block
          // approval; the rest are shown as recommended.
          const { data: sellerRequirements } = await client.sellerRequirements.list({ page: 1, limit: 25 })
      - lang: bash
        label: Spree CLI
        source: spree api get /seller_requirements -d '{"page":1,"limit":25}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - name: page
        in: query
        required: false
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        schema:
          type: integer
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `position` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `name`, `position`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: SellerRequirement
        sortable:
        - created_at
        - id
        - name
        - position
        - updated_at
      responses:
        '200':
          description: seller requirements found
          content:
            application/json:
              example:
                data:
                - id: selreq_UkLWZg9DAJ
                  position: 1
                  active: true
                  required: true
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  kind: accept_terms
                  name: Accept terms
                  description: Read and accept the marketplace terms
                  preferences:
                    terms_body:
                    terms_effective_from:
                    terms_url:
                  custom_field_definition_ids: []
                  allow_multiple: false
                  accepts_submissions: false
                  reviewed_by_operator: 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/SellerRequirement"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
    post:
      summary: Add a seller requirement
      tags:
      - Seller Requirements
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds something the marketplace asks of its sellers.

        `type` comes from `GET /seller_requirements/types`, which also
        describes the configuration each kind takes. Most kinds answer one
        question and can be added once; the open-ended ones — a seller
        confirmation, a manual check, a document — carry the question in your
        own `name` and `description`, so a store may add as many as it needs.

        A kind that reads the seller's own data (their addresses, their
        products, whether they accepted the terms) needs nothing from the
        seller beyond doing it. The others wait for the seller to submit
        something, and the ones you review wait for you.


        **Required scope:** `write_sellers` (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',
          })

          // Asks every seller for a business registration before they can be approved.
          // The wording is yours — `document` is one of the open-ended kinds, so a store
          // can add as many as it needs, each with its own instructions.
          const sellerRequirement = await client.sellerRequirements.create({
            type: 'document',
            name: 'Business registration',
            description: 'A copy of your certificate of incorporation.',
            required: true,
            preferences: { accepted_content_types: ['application/pdf'] },
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /seller_requirements -d '{"type":"document","name":"Business
          registration","description":"A copy of your certificate of incorporation.","required":true,"preferences":{"accepted_content_types":["application/pdf"]}}'
      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: seller requirement created
          content:
            application/json:
              example:
                id: selreq_UkLWZg9DAJ
                position: 1
                active: true
                required: true
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                kind: document
                name: Business registration
                description: Upload this document for the marketplace to review
                preferences: {}
                custom_field_definition_ids: []
                allow_multiple: true
                accepts_submissions: true
                reviewed_by_operator: true
              schema:
                "$ref": "#/components/schemas/SellerRequirement"
        '422':
          description: kind is not registered
          content:
            application/json:
              example:
                error:
                  code: unknown_seller_requirement_type
                  message: Unknown type
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SellerRequirementCreateParams"
        required: true
  "/api/v3/admin/seller_requirements/types":
    get:
      summary: List seller requirement kinds
      tags:
      - Seller Requirements
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The kinds you can add, and the shape of each one's configuration form.

        `configured` says the store already has this kind — meaningful only
        where `allow_multiple` is false. `accepts_submissions` says the seller
        records having done it rather than it being read from their data, and
        `reviewed_by_operator` says what they send waits for you.

        A marketplace that registers its own kind server-side sees it here
        without this endpoint changing.


        **Required scope:** `read_sellers` (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',
          })

          // What you can ask for, and the configuration each kind takes. A kind your own
          // code registers server-side shows up here too.
          const { data: requirementTypes } = await client.sellerRequirements.types()
      - lang: bash
        label: Spree CLI
        source: spree api get /seller_requirements/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: kinds found
          content:
            application/json:
              example:
                data:
                - type: accept_terms
                  name: Accept terms
                  description: Read and accept the marketplace terms
                  allow_multiple: false
                  accepts_submissions: false
                  reviewed_by_operator: false
                  configured: false
                  addable: true
                  accepted_content_types: []
                  association_fields: []
                  schema:
                    type: object
                    properties:
                      terms_body:
                        type:
                        - string
                        - 'null'
                        x-spree-widget: textarea
                      terms_effective_from:
                        type:
                        - string
                        - 'null'
                        format: date
                      terms_url:
                        type:
                        - string
                        - 'null'
                    additionalProperties: false
                - type: complete_profile
                  name: Complete profile
                  description: Fill in the public profile shoppers see
                  allow_multiple: false
                  accepts_submissions: false
                  reviewed_by_operator: false
                  configured: false
                  addable: true
                  accepted_content_types: []
                  association_fields: []
                  schema:
                    type: object
                    properties:
                      require_about:
                        type: boolean
                        default: true
                      require_logo:
                        type: boolean
                        default: true
                      require_cover_photo:
                        type: boolean
                        default: false
                      require_contact_email:
                        type: boolean
                        default: false
                    additionalProperties: false
                - type: billing_address
                  name: Billing address
                  description: The address your payouts are billed from
                  allow_multiple: false
                  accepts_submissions: false
                  reviewed_by_operator: false
                  configured: false
                  addable: true
                  accepted_content_types: []
                  association_fields: []
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: returns_address
                  name: Returns address
                  description: The address customer returns are sent to
                  allow_multiple: false
                  accepts_submissions: false
                  reviewed_by_operator: false
                  configured: false
                  addable: true
                  accepted_content_types: []
                  association_fields: []
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: delivery_method
                  name: Delivery method
                  description: Offer at least one way to ship your orders
                  allow_multiple: false
                  accepts_submissions: false
                  reviewed_by_operator: false
                  configured: false
                  addable: true
                  accepted_content_types: []
                  association_fields: []
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: package_type
                  name: Shipping box
                  description: Tell us the size and weight of the box you ship orders
                    in
                  allow_multiple: false
                  accepts_submissions: false
                  reviewed_by_operator: false
                  configured: false
                  addable: true
                  accepted_content_types: []
                  association_fields: []
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: minimum_products
                  name: Minimum products
                  description: List at least this many products
                  allow_multiple: false
                  accepts_submissions: false
                  reviewed_by_operator: false
                  configured: false
                  addable: true
                  accepted_content_types: []
                  association_fields: []
                  schema:
                    type: object
                    properties:
                      minimum_count:
                        type: integer
                        default: 1
                    additionalProperties: false
                - type: payout_account
                  name: Payout Account
                  description: ''
                  allow_multiple: false
                  accepts_submissions: false
                  reviewed_by_operator: false
                  configured: false
                  addable: true
                  accepted_content_types: []
                  association_fields: []
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: required_custom_fields
                  name: Required custom fields
                  description: Fill in the details the marketplace asks for
                  allow_multiple: false
                  accepts_submissions: false
                  reviewed_by_operator: false
                  configured: false
                  addable: true
                  accepted_content_types: []
                  association_fields:
                  - custom_field_definition_ids
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: policy
                  name: Seller policy
                  description: Publish a policy with this name
                  allow_multiple: true
                  accepts_submissions: false
                  reviewed_by_operator: false
                  configured: false
                  addable: true
                  accepted_content_types: []
                  association_fields: []
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: attestation
                  name: Seller confirmation
                  description: Confirm this yourself before you are approved
                  allow_multiple: true
                  accepts_submissions: true
                  reviewed_by_operator: false
                  configured: false
                  addable: true
                  accepted_content_types: []
                  association_fields: []
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: operator_review
                  name: Manual check
                  description: The marketplace checks this by hand before approving
                    you
                  allow_multiple: true
                  accepts_submissions: true
                  reviewed_by_operator: true
                  configured: false
                  addable: true
                  accepted_content_types: []
                  association_fields: []
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
                - type: document
                  name: Document
                  description: Upload this document for the marketplace to review
                  allow_multiple: true
                  accepts_submissions: true
                  reviewed_by_operator: true
                  configured: false
                  addable: true
                  accepted_content_types:
                  - application/pdf
                  - image/jpeg
                  - image/png
                  - image/heic
                  - image/webp
                  - application/msword
                  - application/vnd.openxmlformats-officedocument.wordprocessingml.document
                  association_fields: []
                  schema:
                    type: object
                    properties: {}
                    additionalProperties: false
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        type:
                          type: string
                          example: document
                        name:
                          type: string
                          example: Document
                        description:
                          type: string
                          example: A file the seller uploads and you review
                        allow_multiple:
                          type: boolean
                          example: true
                        accepts_submissions:
                          type: boolean
                          example: true
                        reviewed_by_operator:
                          type: boolean
                          example: true
                        configured:
                          type: boolean
                          example: false
                        addable:
                          type: boolean
                          example: true
                          description: Whether the operator may add one now. The uniqueness
                            rule is the server's, so clients filter on this rather
                            than deriving it.
                        schema:
                          type: object
                          description: JSON Schema of the type's `preferences`
  "/api/v3/admin/seller_requirements/{id}":
    parameters:
    - name: id
      in: path
      required: true
      schema:
        type: string
    patch:
      summary: Update a seller requirement
      tags:
      - Seller Requirements
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Changes how a requirement is worded, what it asks for, where it sits in
        the checklist, and whether it blocks approval.

        `type` is not accepted: a saved row's kind never changes, because
        anything a seller already submitted answered the old one.


        **Required scope:** `write_sellers` (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',
          })

          // Asks for three products instead of one. Sellers who already met the old
          // number see this return to their checklist.
          const sellerRequirement = await client.sellerRequirements.update('selreq_a1b2c3', {
            preferences: { minimum_count: 3 },
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /seller_requirements/{id} -d '{"preferences":{"minimum_count":3}}'
      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: seller requirement updated
          content:
            application/json:
              example:
                id: selreq_UkLWZg9DAJ
                position: 1
                active: true
                required: true
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                kind: minimum_products
                name: Minimum products
                description: List at least this many products
                preferences:
                  minimum_count: 3
                custom_field_definition_ids: []
                allow_multiple: false
                accepts_submissions: false
                reviewed_by_operator: false
              schema:
                "$ref": "#/components/schemas/SellerRequirement"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SellerRequirementUpdateParams"
        required: true
    delete:
      summary: Delete a seller requirement
      tags:
      - Seller Requirements
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Stops asking for this. Anything sellers already submitted against it
        goes too — to keep the record while pausing the ask, set `active` to
        false instead.


        **Required scope:** `write_sellers` (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',
          })

          // Stops asking for this, and deletes what sellers submitted against it. To
          // keep the record while pausing the ask, update it with `active: false`.
          await client.sellerRequirements.delete('selreq_a1b2c3')
      - lang: bash
        label: Spree CLI
        source: spree api delete /seller_requirements/{id}
      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: seller requirement deleted
  "/api/v3/admin/sellers":
    get:
      summary: List sellers
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the sellers on this marketplace. `status` says where each one
        is in its life on the marketplace, and `sellable` answers the question
        the status alone cannot: an approved seller who is away cannot be
        bought from either.


        **Required scope:** `read_sellers` (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',
          })

          // `sellable` is the one to read for "can this seller be bought from" — an
          // approved seller who is away answers false.
          const { data: sellers } = await client.sellers.list({ page: 1, limit: 25 })
      - lang: bash
        label: Spree CLI
        source: spree api get /sellers -d '{"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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: sort
        in: query
        required: false
        description: Sort by field. Prefix with `-` for descending (e.g., `-created_at`).
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `contact_email` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `status` | One of `pending`, `invited`, `canceled`, `onboarding`, `ready_for_review`, `approved`, `rejected`, `suspended` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Seller
        sortable:
        - contact_email
        - created_at
        - id
        - name
        - status
        - updated_at
      responses:
        '200':
          description: sellers found
          content:
            application/json:
              example:
                data:
                - id: sel_UkLWZg9DAJ
                  name: Sparks Audio
                  slug: sparks-audio
                  about: ''
                  about_html: ''
                  logo_url:
                  square_logo_url:
                  cover_photo_url:
                  external_references: {}
                  status: pending
                  contact_email: hello@sparks.example
                  billing_email:
                  tax_remittance: seller
                  payouts_schedule_interval:
                  metadata: {}
                  holiday_mode_until:
                  terms_accepted_at:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  deleted_at:
                  minimum_payout_amount:
                  on_holiday: false
                  sellable: false
                  products_count: 0
                  products_count_by_status:
                    draft: 0
                    active: 0
                    archived: 0
                    proposed: 0
                    rejected: 0
                  users_count: 0
                  onboarding_progress:
                    done: 0
                    total: 0
                  onboarding_complete: true
                  legal_name:
                  registration_number:
                  returns_location_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/Seller"
                  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 seller
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Opens a seller record. The seller starts as `pending` and has no team
        yet — invite someone to run it with the `invite` action below.

        `status` is deliberately not writable here or on update: every move
        through the lifecycle is its own action, because each one does more
        than set a column.


        **Required scope:** `write_sellers` (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',
          })

          // The seller starts as `pending` and has no team yet — invite someone to run
          // it next.
          const seller = await client.sellers.create({
            name: 'Northwind Books',
            contact_email: 'hi@northwind.example',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /sellers -d '{"name":"Northwind Books","contact_email":"hi@northwind.example"}'
      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: seller created
          content:
            application/json:
              example:
                id: sel_gbHJdmfrXB
                name: Northwind Books
                slug: northwind-books
                about: ''
                about_html: ''
                logo_url:
                square_logo_url:
                cover_photo_url:
                external_references: {}
                status: pending
                contact_email: hi@northwind.example
                billing_email:
                tax_remittance: seller
                payouts_schedule_interval:
                metadata: {}
                holiday_mode_until:
                terms_accepted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                minimum_payout_amount:
                on_holiday: false
                sellable: false
                products_count: 0
                products_count_by_status:
                  draft: 0
                  active: 0
                  archived: 0
                  proposed: 0
                  rejected: 0
                users_count: 0
                onboarding_progress:
                  done: 0
                  total: 0
                onboarding_complete: true
                legal_name:
                registration_number:
                returns_location_id: sloc_UkLWZg9DAJ
              schema:
                "$ref": "#/components/schemas/Seller"
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank and Slug can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
                    slug:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SellerCreateParams"
        required: true
  "/api/v3/admin/sellers/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Seller prefixed ID
      schema:
        type: string
    get:
      summary: Get a seller
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a single seller, including its settlement and tax configuration.

        **Required scope:** `read_sellers` (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 seller = await client.sellers.get('sel_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /sellers/{id}
      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: seller found
          content:
            application/json:
              example:
                id: sel_UkLWZg9DAJ
                name: Sparks Audio
                slug: sparks-audio
                about: ''
                about_html: ''
                logo_url:
                square_logo_url:
                cover_photo_url:
                external_references: {}
                status: pending
                contact_email: hello@sparks.example
                billing_email:
                tax_remittance: seller
                payouts_schedule_interval:
                metadata: {}
                holiday_mode_until:
                terms_accepted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                minimum_payout_amount:
                on_holiday: false
                sellable: false
                products_count: 0
                products_count_by_status:
                  draft: 0
                  active: 0
                  archived: 0
                  proposed: 0
                  rejected: 0
                users_count: 0
                onboarding_progress:
                  done: 0
                  total: 0
                onboarding_complete: true
                legal_name:
                registration_number:
                returns_location_id:
              schema:
                "$ref": "#/components/schemas/Seller"
        '404':
          description: seller not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Seller not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update a seller
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Updates the seller's profile and the settlement configuration the
        operator owns. A `status` sent here is ignored — use the lifecycle
        actions.


        **Required scope:** `write_sellers` (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',
          })

          // `status` is not writable here: each move through the lifecycle is its own
          // action, because each one does more than set a column.
          const seller = await client.sellers.update('sel_UkLWZg9DAJ', {
            billing_email: 'billing@northwind.example',
            payouts_schedule_interval: 'weekly',
            minimum_payout_amount: '25.0',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /sellers/{id} -d '{"billing_email":"billing@northwind.example","payouts_schedule_interval":"weekly","minimum_payout_amount":"25.0"}'
      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: seller address written inline
          content:
            application/json:
              example:
                id: sel_UkLWZg9DAJ
                name: Sparks Audio
                slug: sparks-audio
                about: ''
                about_html: ''
                logo_url:
                square_logo_url:
                cover_photo_url:
                external_references: {}
                status: pending
                contact_email: hello@sparks.example
                billing_email:
                tax_remittance: seller
                payouts_schedule_interval:
                metadata: {}
                holiday_mode_until:
                terms_accepted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                minimum_payout_amount:
                on_holiday: false
                sellable: false
                products_count: 0
                products_count_by_status:
                  draft: 0
                  active: 0
                  archived: 0
                  proposed: 0
                  rejected: 0
                users_count: 0
                onboarding_progress:
                  done: 0
                  total: 0
                onboarding_complete: true
                legal_name:
                registration_number:
                returns_location_id:
                billing_address:
                  id: addr_UkLWZg9DAJ
                  label:
                  first_name:
                  last_name:
                  full_name: ''
                  address1: 1 Seller Way
                  address2:
                  postal_code: EC1A 1BB
                  city: London
                  phone: '555'
                  company: Sparks Trading Ltd
                  country_name: United Kingdom
                  country_code: GB
                  state_text:
                  state_code:
                  quick_checkout: false
                  is_default_billing: false
                  is_default_shipping: false
                  state_name:
                  owner:
                    id: sel_UkLWZg9DAJ
                    type: seller
                    name:
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  latitude:
                  longitude:
                  customer_id:
              schema:
                "$ref": "#/components/schemas/Seller"
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SellerUpdateParams"
        required: true
    delete:
      summary: Delete a seller
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Soft-deletes the seller. Their products are kept and left without a
        seller rather than deleted — what happens to a departed seller's
        catalog is the operator's decision.


        **Required scope:** `write_sellers` (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 seller. Their products stay in the catalog without a
          // seller rather than being deleted with them.
          await client.sellers.delete('sel_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api delete /sellers/{id}
      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: seller deleted
  "/api/v3/admin/sellers/{id}/invite":
    parameters:
    - name: id
      in: path
      required: true
      description: Seller prefixed ID
      schema:
        type: string
    post:
      summary: Invite someone to run a seller
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Sends an invitation to the seller's own team and moves the seller to
        `invited`. The person becomes a member when they accept, and can then
        sign in to the seller panel.

        `role_id` must name a role this seller owns; omit it for the seller's
        own admin role. Re-inviting is allowed — an invitation expires, or the
        first one goes to the wrong address.


        **Required scope:** `write_sellers` (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',
          })

          // They join the seller's team when they accept, and can then sign in to the
          // seller panel. Omit `role_id` for the seller's own admin role.
          const seller = await client.sellers.invite('sel_UkLWZg9DAJ', {
            email: 'seller@northwind.example',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /sellers/{id}/invite -d '{"email":"seller@northwind.example"}'
      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 sent
          content:
            application/json:
              example:
                id: sel_UkLWZg9DAJ
                name: Sparks Audio
                slug: sparks-audio
                about: ''
                about_html: ''
                logo_url:
                square_logo_url:
                cover_photo_url:
                external_references: {}
                status: invited
                contact_email: hello@sparks.example
                billing_email:
                tax_remittance: seller
                payouts_schedule_interval:
                metadata: {}
                holiday_mode_until:
                terms_accepted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                minimum_payout_amount:
                on_holiday: false
                sellable: false
                products_count: 0
                products_count_by_status:
                  draft: 0
                  active: 0
                  archived: 0
                  proposed: 0
                  rejected: 0
                users_count: 0
                onboarding_progress:
                  done: 0
                  total: 0
                onboarding_complete: true
                legal_name:
                registration_number:
                returns_location_id:
              schema:
                "$ref": "#/components/schemas/Seller"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SellerInviteParams"
        required: true
  "/api/v3/admin/sellers/{seller_id}/invitations":
    parameters:
    - name: seller_id
      in: path
      required: true
      description: Seller prefixed ID
      schema:
        type: string
    post:
      summary: Invite someone to a seller team
      tags:
      - Sellers
      operationId: sellers_invite_team_member
      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',
          })

          // Adds someone to the seller's team without changing the seller's status.
          const invitation = await client.sellers.invitations.create('sel_UkLWZg9DAJ', {
            email: 'teammate@northwind.example',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /sellers/{seller_id}/invitations -d '{"email":"teammate@northwind.example"}'
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Invites someone to join the seller's team with the seller's own admin
        role. They become a member when they accept. Unlike the seller's
        `invite` action, this leaves the seller's status unchanged, so use it to
        add people to a seller that is already approved.


        **Required scope:** `write_sellers` (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: invitation sent
          content:
            application/json:
              example:
                id: inv_UkLWZg9DAJ
                email: teammate@example.com
                status: pending
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                expires_at: '2026-01-29T12:00:00.000Z'
                role_id: role_gbHJdmfrXB
                role_name: admin
                inviter_email: marta@nikolaus.com
                invitee_exists: false
                store:
                  id: store_UkLWZg9DAJ
                  name: Spree Test Store
              schema:
                "$ref": "#/components/schemas/Invitation"
        '422':
          description: invalid email
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Email is invalid
                  details:
                    email:
                    - value: nope
                      code: invalid
                      message: is invalid
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SellerInvitationCreateParams"
        required: true
  "/api/v3/admin/sellers/{seller_id}/invitations/{id}/resend":
    parameters:
    - name: seller_id
      in: path
      required: true
      description: Seller prefixed ID
      schema:
        type: string
    - name: id
      in: path
      required: true
      description: Invitation prefixed ID
      schema:
        type: string
    patch:
      summary: Resend a seller invitation
      tags:
      - Sellers
      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.sellers.invitations.resend('seller_UkLWZg9DAJ', 'inv_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api patch /sellers/{seller_id}/invitations/{id}/resend -d '{
          ... }'
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Sends a pending invitation to the seller's team again, with a fresh
        acceptance link. Use it when the email never arrived; an invitation that
        has expired is refused, so invite the person again instead.


        **Required scope:** `write_sellers` (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: invitation resent
          content:
            application/json:
              example:
                id: inv_UkLWZg9DAJ
                email: gaye@rutherfordmosciski.co.uk
                status: pending
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                expires_at: '2026-01-29T12:00:00.000Z'
                role_id: role_UkLWZg9DAJ
                role_name: admin
                inviter_email: carman@schambergernicolas.ca
                invitee_exists: false
                store:
                  id: store_UkLWZg9DAJ
                  name: Spree Test Store
              schema:
                "$ref": "#/components/schemas/Invitation"
        '422':
          description: the invitation has expired
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: This invitation has expired. Invite them again to send
                    a new one.
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/sellers/{id}/approve":
    parameters:
    - name: id
      in: path
      required: true
      description: Seller prefixed ID
      schema:
        type: string
    patch:
      summary: Approve a seller
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Lets the seller sell. This is also the way back for one that was
        suspended or turned down, and it clears any holiday along with the
        suspension.


        **Required scope:** `write_sellers` (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',
          })

          // Also the way back for a seller that was suspended or turned down — and it
          // clears any holiday along with the suspension.
          const seller = await client.sellers.approve('sel_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api patch /sellers/{id}/approve -d '{ ... }'
      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: seller approved
          content:
            application/json:
              example:
                id: sel_UkLWZg9DAJ
                name: Sparks Audio
                slug: sparks-audio
                about: ''
                about_html: ''
                logo_url:
                square_logo_url:
                cover_photo_url:
                external_references: {}
                status: approved
                contact_email: hello@sparks.example
                billing_email:
                tax_remittance: seller
                payouts_schedule_interval:
                metadata: {}
                holiday_mode_until:
                terms_accepted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                minimum_payout_amount:
                on_holiday: false
                sellable: true
                products_count: 0
                products_count_by_status:
                  draft: 0
                  active: 0
                  archived: 0
                  proposed: 0
                  rejected: 0
                users_count: 0
                onboarding_progress:
                  done: 0
                  total: 0
                onboarding_complete: true
                legal_name:
                registration_number:
                returns_location_id:
              schema:
                "$ref": "#/components/schemas/Seller"
        '422':
          description: seller cannot be approved from its current status
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: Already approved
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SellerApproveParams"
        required: true
  "/api/v3/admin/sellers/{id}/reopen_onboarding":
    parameters:
    - name: id
      in: path
      required: true
      description: Seller prefixed ID
      schema:
        type: string
    patch:
      summary: Send a seller back to onboarding
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Hands an application back to the seller to finish, rather than
        approving or rejecting it. Only a seller whose application is ready
        for review can be sent back, and the note says what is missing.


        **Required scope:** `write_sellers` (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',
          })

          // The note tells the seller what to fix before they submit again.
          const seller = await client.sellers.reopenOnboarding('sel_UkLWZg9DAJ', {
            note: 'Please upload a bank statement dated within the last 3 months.',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /sellers/{id}/reopen_onboarding -d '{"note":"Please
          upload a bank statement dated within the last 3 months."}'
      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: seller back in onboarding
          content:
            application/json:
              example:
                id: sel_UkLWZg9DAJ
                name: Sparks Audio
                slug: sparks-audio
                about: ''
                about_html: ''
                logo_url:
                square_logo_url:
                cover_photo_url:
                external_references: {}
                status: onboarding
                contact_email: hello@sparks.example
                billing_email:
                tax_remittance: seller
                payouts_schedule_interval:
                metadata:
                  onboarding_reopened_note: Your bank details do not match the registered
                    business name.
                holiday_mode_until:
                terms_accepted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                minimum_payout_amount:
                on_holiday: false
                sellable: false
                products_count: 0
                products_count_by_status:
                  draft: 0
                  active: 0
                  archived: 0
                  proposed: 0
                  rejected: 0
                users_count: 0
                onboarding_progress:
                  done: 0
                  total: 0
                onboarding_complete: true
                legal_name:
                registration_number:
                returns_location_id:
              schema:
                "$ref": "#/components/schemas/Seller"
        '422':
          description: the seller is not awaiting review
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: Not reopenable
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                note:
                  type: string
                  description: What the seller still has to supply
                  example: Your bank details do not match the registered business
                    name.
  "/api/v3/admin/sellers/{id}/suspend":
    parameters:
    - name: id
      in: path
      required: true
      description: Seller prefixed ID
      schema:
        type: string
    patch:
      summary: Suspend a seller
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Stops a trading seller from selling. Their catalog and history stay,
        and approving reinstates them. Use this rather than `reject` for a
        seller already on the marketplace — it says something different, and
        it can be undone.


        **Required scope:** `write_sellers` (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',
          })

          // Stops a trading seller from selling. Their catalog and history stay, and
          // approving reinstates them.
          const seller = await client.sellers.suspend('sel_UkLWZg9DAJ', {
            reason: 'Counterfeit goods',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /sellers/{id}/suspend -d '{"reason":"Counterfeit goods"}'
      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: seller suspended
          content:
            application/json:
              example:
                id: sel_UkLWZg9DAJ
                name: Sparks Audio
                slug: sparks-audio
                about: ''
                about_html: ''
                logo_url:
                square_logo_url:
                cover_photo_url:
                external_references: {}
                status: suspended
                contact_email: hello@sparks.example
                billing_email:
                tax_remittance: seller
                payouts_schedule_interval:
                metadata:
                  suspension_reason: Counterfeit goods
                holiday_mode_until:
                terms_accepted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                minimum_payout_amount:
                on_holiday: false
                sellable: false
                products_count: 0
                products_count_by_status:
                  draft: 0
                  active: 0
                  archived: 0
                  proposed: 0
                  rejected: 0
                users_count: 0
                onboarding_progress:
                  done: 0
                  total: 0
                onboarding_complete: true
                legal_name:
                registration_number:
                returns_location_id:
              schema:
                "$ref": "#/components/schemas/Seller"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SellerSuspendParams"
        required: true
  "/api/v3/admin/sellers/{id}/reject":
    parameters:
    - name: id
      in: path
      required: true
      description: Seller prefixed ID
      schema:
        type: string
    patch:
      summary: Reject a seller
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Turns down an applicant who never traded. A seller already selling is
        suspended instead; rejecting one is refused.


        **Required scope:** `write_sellers` (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',
          })

          // For an applicant who never traded. A seller already selling is suspended
          // instead.
          const seller = await client.sellers.reject('sel_UkLWZg9DAJ', {
            reason: 'Incomplete paperwork',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /sellers/{id}/reject -d '{"reason":"Incomplete paperwork"}'
      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: seller rejected
          content:
            application/json:
              example:
                id: sel_UkLWZg9DAJ
                name: Sparks Audio
                slug: sparks-audio
                about: ''
                about_html: ''
                logo_url:
                square_logo_url:
                cover_photo_url:
                external_references: {}
                status: rejected
                contact_email: hello@sparks.example
                billing_email:
                tax_remittance: seller
                payouts_schedule_interval:
                metadata:
                  rejection_reason: Incomplete paperwork
                holiday_mode_until:
                terms_accepted_at:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                minimum_payout_amount:
                on_holiday: false
                sellable: false
                products_count: 0
                products_count_by_status:
                  draft: 0
                  active: 0
                  archived: 0
                  proposed: 0
                  rejected: 0
                users_count: 0
                onboarding_progress:
                  done: 0
                  total: 0
                onboarding_complete: true
                legal_name:
                registration_number:
                returns_location_id:
              schema:
                "$ref": "#/components/schemas/Seller"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SellerRejectParams"
        required: true
  "/api/v3/admin/sellers/{seller_id}/balances":
    parameters:
    - name: seller_id
      in: path
      required: true
      description: Seller prefixed ID
      schema:
        type: string
    get:
      summary: List a seller's balances
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Where one seller stands with the marketplace, one row per currency:
        what they have earned (completed transfers, refund reversals
        included), what has been paid to them, what is still owed, and
        earnings the payout provider has not yet confirmed.

        Computed from the ledger rather than stored, so the rows carry no id.


        **Required scope:** `read_payouts` (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',
          })

          // One row per currency: earned, paid, still owed, and not yet confirmed.
          const { data: balances } = await client.sellers.balances('sel_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api get /sellers/{seller_id}/balances
      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: balances listed
          content:
            application/json:
              example:
                data:
                - currency: USD
                  settlement_currency: USD
                  converted: false
                  seller_id: sel_UkLWZg9DAJ
                  earned: '40.00'
                  pending: '0.00'
                  payable: '40.00'
                  paid: '0.00'
                  balance: '40.00'
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/SellerBalance"
                required:
                - data
        '404':
          description: seller not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Seller not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/sellers/{seller_id}/payouts":
    parameters:
    - name: seller_id
      in: path
      required: true
      description: Seller prefixed ID
      schema:
        type: string
    post:
      summary: Settle a seller
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Sweeps everything this seller is owed into a payout — one per currency,
        since nothing is ever converted between them.

        This is what the `manual` payout interval means: the scheduled sweep
        runs on each seller's own interval and skips anyone set to `manual`,
        leaving the operator to decide when. It also settles any other seller
        early.

        It records the settlement rather than sending money: the built-in
        provider waits to be told the bank transfer went out, which is
        `PATCH /api/v3/admin/seller_payouts/{id}/complete`.

        Answers `422` when there is nothing to settle — no payout account,
        nothing unsettled, or a balance below the seller's minimum.


        **Required scope:** `write_payouts` (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',
          })

          // Pays out everything the seller is owed now, one payout per currency.
          const { data: payouts } = await client.sellers.settle('sel_UkLWZg9DAJ')
      - lang: bash
        label: Spree CLI
        source: spree api post /sellers/{seller_id}/payouts -d '{ ... }'
      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: seller settled
          content:
            application/json:
              example:
                data:
                - id: vpo_UkLWZg9DAJ
                  status: pending
                  currency: USD
                  reference:
                  metadata: {}
                  period_start: '2026-01-15T12:00:00.000Z'
                  period_end: '2026-01-15T12:00:00.000Z'
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  amount: '40.00'
                  seller_id: sel_UkLWZg9DAJ
                  seller_name: Sparks Audio
                  transfers_count: 1
                  provider: system
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/SellerPayout"
                required:
                - data
        '422':
          description: nothing to settle
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: This seller has nothing to settle right now.
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/seller_transfers":
    get:
      summary: List seller transfers
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The fund ledger: what each seller earned from an order, and any
        reversals. Read-only, since fulfilment and refunds write it.


        **Required scope:** `read_payouts` (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: transfers } = await client.sellerTransfers.list({
            seller_name_cont: 'Acme',
            created_at_gteq: '2026-09-01',
            sort: '-created_at',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /seller_transfers -d '{"seller_name_cont":"Acme","created_at_gteq":"2026-09-01","sort":"-created_at"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of reference (partial, case-insensitive).
      - name: page
        in: query
        required: false
        description: Page number
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        description: Records per page (max 100)
        schema:
          type: integer
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[provider_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `amount` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `currency` | One of the `CurrencyCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `kind` | One of `earning`, `refund_reversal` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `order_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `payout_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `provider` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `reference` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `seller_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `status` | One of `pending`, `processing`, `completed`, `failed`, `unresolved` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[payout_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `payout_` | `amount`, `created_at`, `currency`, `id`, `period_end`, `period_start`, `provider`, `reference`, `seller_id`, `status`, `updated_at` |
          | `payout_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `refund_` | `created_at`, `id`, `updated_at` |
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |

          </Accordion>

          **Sort by:** `amount`, `created_at`, `currency`, `id`, `kind`, `order_id`, `payout_id`, `provider`, `reference`, `seller_id`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: SellerTransfer
        sortable:
        - amount
        - created_at
        - currency
        - id
        - kind
        - order_id
        - payout_id
        - provider
        - reference
        - seller_id
        - status
        - updated_at
      responses:
        '200':
          description: transfers listed
          content:
            application/json:
              example:
                data:
                - id: vtr_UkLWZg9DAJ
                  kind: earning
                  status: completed
                  currency: USD
                  reference:
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  amount: '40.00'
                  settled_amount: '40.00'
                  settled_currency: USD
                  converted: false
                  seller_id: sel_UkLWZg9DAJ
                  order_id: or_UkLWZg9DAJ
                  payout_id:
                  reversed_from_id:
                  refund_id:
                  seller_name: Sparks Audio
                  order_number: R1001
                  provider: system
                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/SellerTransfer"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/seller_payouts":
    get:
      summary: List seller payouts
      tags:
      - Sellers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Settlements to sellers, each batching the transfers that had
        accumulated since the last. `pending` and `processing` payouts are
        still owed; `completed` ones reached the seller.


        **Required scope:** `read_payouts` (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: payouts } = await client.sellerPayouts.list({
            period_end_gteq: '2026-09-01',
            sort: '-created_at',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /seller_payouts -d '{"period_end_gteq":"2026-09-01","sort":"-created_at"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of reference (partial, case-insensitive).
      - name: page
        in: query
        required: false
        description: Page number
        schema:
          type: integer
      - name: limit
        in: query
        required: false
        description: Records per page (max 100)
        schema:
          type: integer
      - name: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[provider_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `amount` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `currency` | One of the `CurrencyCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `period_end` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `period_start` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `provider` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `reference` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `seller_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `status` | One of `pending`, `processing`, `completed`, `failed`, `unresolved` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[seller_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |

          </Accordion>

          **Sort by:** `amount`, `created_at`, `currency`, `id`, `period_end`, `period_start`, `provider`, `reference`, `seller_id`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: SellerPayout
        sortable:
        - amount
        - created_at
        - currency
        - id
        - period_end
        - period_start
        - provider
        - reference
        - seller_id
        - status
        - updated_at
      responses:
        '200':
          description: payouts listed
          content:
            application/json:
              example:
                data:
                - id: vpo_UkLWZg9DAJ
                  status: pending
                  currency: USD
                  reference:
                  metadata: {}
                  period_start:
                  period_end:
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  amount: '40.00'
                  seller_id: sel_UkLWZg9DAJ
                  seller_name: Sparks Audio
                  transfers_count: 0
                  provider: system
                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/SellerPayout"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/seller_payouts/{id}/complete":
    parameters:
    - name: id
      in: path
      required: true
      description: Seller payout prefixed ID
      schema:
        type: string
    patch:
      summary: Mark a payout paid
      tags:
      - Sellers
      x-spree-agent: false
      x-spree-agent-reason: Settles a payout against the payment provider, reconciling
        against provider state an agent cannot see.
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Records that the money reached the seller, which is what debits their
        balance — a balance is earnings less *completed* settlements.

        This is the step the built-in provider waits for: it files the
        settlement when the payout is created and expects an operator to say
        the bank transfer went out. A connected provider marks its own payouts
        paid when its webhook reports the money landed.

        Send the provider's own id for the transfer as `reference` when there
        is one. Completing a payout that is already complete answers `200`
        without recording it twice, so a redelivered webhook or a double click
        is safe.


        **Required scope:** `write_payouts` (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',
          })

          // Records that the bank transfer went out.
          const payout = await client.sellerPayouts.complete('vpo_UkLWZg9DAJ', {
            reference: 'BANK-TRF-20261012-0042',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /seller_payouts/{id}/complete -d '{"reference":"BANK-TRF-20261012-0042"}'
      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: payout completed
          content:
            application/json:
              example:
                id: vpo_UkLWZg9DAJ
                status: completed
                currency: USD
                reference: TRF-8842
                metadata: {}
                period_start:
                period_end:
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                amount: '40.00'
                seller_id: sel_UkLWZg9DAJ
                seller_name: Sparks Audio
                transfers_count: 0
                provider: system
              schema:
                "$ref": "#/components/schemas/SellerPayout"
        '404':
          description: payout not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Seller payout not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SellerPayoutCompleteParams"
        required: true
  "/api/v3/admin/stock_levels":
    get:
      summary: List stock levels
      tags:
      - Stock
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        One row per variant per stock location, carrying every figure the
        Inventory page shows: `count_on_hand` (on hand), `allocated_count`
        (committed to placed orders), `reserved_count` (held by checkouts in
        progress), `available_count` (on hand minus committed) and
        `incoming_count` (on its way on an open purchase order or a transfer
        in transit). The variant and location are named flat on the row
        (`variant_name`, `variant_sku`, `stock_location_name`, `thumbnail_url`)
        so a list needs no expansion.

        Filter with `q[stock_location_id_eq]`, `q[variant_id_eq]` or
        `q[variant_sku_or_variant_product_name_cont]`.


        **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',
          })

          // One row per variant per location: on hand, committed, reserved, available
          // and incoming, with the variant and location named flat on the row.
          const { data: stockLevels } = await client.stockLevels.list({
            stock_location_id_eq: 'sloc_xxx',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /stock_levels -d '{"stock_location_id_eq":"sloc_xxx"}'
      parameters:
      - name: x-spree-api-key
        in: header
        required: true
        schema:
          type: string
      - name: Authorization
        in: header
        required: true
        schema:
          type: string
      - name: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of variant sku and variant product name (partial,
          case-insensitive).
      - name: q[with_stock_status][]
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        description: Applies `with_stock_status` to the given value.
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[allocated_count_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `allocated_count` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `count_on_hand` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `incoming_count` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `reserved_count` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `stock_location_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `variant_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[stock_location_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `stock_location_` | `active`, `country_code`, `created_at`, `default`, `id`, `kind`, `name`, `pickup_enabled`, `returns_enabled`, `seller_id`, `state_code`, `updated_at` |
          | `stock_location_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `variant_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `variant_option_values_` | `created_at`, `id`, `label`, `name`, `position`, `updated_at` |
          | `variant_prices_` | `amount`, `compare_at_amount`, `created_at`, `currency`, `id`, `min_quantity`, `price_list_id`, `updated_at`, `variant_id` |
          | `variant_product_` | `available_on`, `created_at`, `description`, `discontinue_on`, `id`, `name`, `price`, `seller_id`, `slug`, `status`, `updated_at` |
          | `variant_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `variant_tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |

          </Accordion>

          **Sort by:** `allocated_count`, `count_on_hand`, `created_at`, `id`, `incoming_count`, `reserved_count`, `stock_location_id`, `updated_at`, `variant_id`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: StockLevel
        sortable:
        - allocated_count
        - count_on_hand
        - created_at
        - id
        - incoming_count
        - reserved_count
        - stock_location_id
        - updated_at
        - variant_id
      responses:
        '200':
          description: stock levels found
          content:
            application/json:
              example:
                data:
                - id: sl_UkLWZg9DAJ
                  count_on_hand: 0
                  backorderable: true
                  stock_location_id: sloc_UkLWZg9DAJ
                  variant_id: variant_UkLWZg9DAJ
                  external_references: {}
                  metadata: {}
                  reserved_count: 0
                  incoming_count: 0
                  purchasable_count: 0
                  variant_name: Product 2135410
                  variant_sku: SKU-260
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  stock_location_name: Jong Schamberger
                  product_id: prod_UkLWZg9DAJ
                  options_text:
                  thumbnail_url:
                  allocated_count: 0
                  available_count: 0
                - id: sl_gbHJdmfrXB
                  count_on_hand: 0
                  backorderable: true
                  stock_location_id: sloc_UkLWZg9DAJ
                  variant_id: variant_gbHJdmfrXB
                  external_references: {}
                  metadata: {}
                  reserved_count: 0
                  incoming_count: 0
                  purchasable_count: 0
                  variant_name: Product 2135410
                  variant_sku: SKU-261
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  stock_location_name: Jong Schamberger
                  product_id: prod_UkLWZg9DAJ
                  options_text: 'Size: S'
                  thumbnail_url:
                  allocated_count: 0
                  available_count: 0
                - id: sl_EfhxLZ9ck8
                  count_on_hand: 40
                  backorderable: true
                  stock_location_id: sloc_gbHJdmfrXB
                  variant_id: variant_gbHJdmfrXB
                  external_references: {}
                  metadata: {}
                  reserved_count: 2
                  incoming_count: 20
                  purchasable_count: 35
                  variant_name: Product 2135410
                  variant_sku: SKU-261
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  stock_location_name: Pilar Stokes
                  product_id: prod_UkLWZg9DAJ
                  options_text: 'Size: S'
                  thumbnail_url:
                  allocated_count: 3
                  available_count: 37
                meta:
                  page: 1
                  limit: 25
                  count: 3
                  pages: 1
                  from: 1
                  to: 3
                  in: 3
                  previous:
                  next:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      "$ref": "#/components/schemas/StockLevel"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/stock_levels/bulk_upsert":
    post:
      summary: Bulk-upsert stock levels
      tags:
      - Stock
      x-spree-agent: false
      x-spree-agent-reason: set_stock calls this endpoint already, taking stock by
        SKU and location the way a merchant names them.
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Sets stock levels for many (variant, location) pairs at once — what a
        warehouse or ERP feed posts on a schedule.

        Each row names its variant and stock location by Spree id
        (`variant_id`, `stock_location_id`).

        A row carries either `count_on_hand` — the absolute level the external
        system reports — or `adjustment`, a relative change for feeds that
        report movements instead. Every change is written as a stock movement,
        so a merchant can still see why a figure moved.

        The response carries `stock_level_count`: how many rows moved a shelf.


        **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 { stock_level_count } = await client.stockLevels.bulkUpsert({
            stock_levels: [
              {
                variant_id: 'variant_xxx',
                stock_location_id: 'sloc_xxx',
                count_on_hand: 42,
              },
            ],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /stock_levels/bulk_upsert -d '{"stock_levels":[{"variant_id":"variant_xxx","stock_location_id":"sloc_xxx","count_on_hand":42}]}'
      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: stock levels updated
          content:
            application/json:
              example:
                stock_level_count: 1
        '422':
          description: row is missing a level
          content:
            application/json:
              example:
                error:
                  code: invalid_stock_levels
                  message: Each row must name a variant and stock location in this
                    store, and either a count_on_hand or an adjustment.
                  details:
                    rows:
                    - index: 0
                      missing:
                      - count_on_hand
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/StockLevelBulkUpsertParams"
        required: true
  "/api/v3/admin/stock_levels/{id}":
    patch:
      summary: Update a stock level
      tags:
      - Stock
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Corrects one shelf. Send `count_on_hand` for the count the shelf should
        end at, or `adjustment` for a signed change; either is recorded as a
        stock movement labelled with `reason`.


        **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',
          })

          // Sets the count the shelf should end at; the difference is recorded in the stock history.
          const stockLevel = await client.stockLevels.update('sl_UkLWZg9DAJ', {
            count_on_hand: 42,
            reason: 'Cycle count',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /stock_levels/{id} -d '{"count_on_hand":42,"reason":"Cycle
          count"}'
      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: Stock level ID
        schema:
          type: string
      responses:
        '200':
          description: stock level updated
          content:
            application/json:
              example:
                id: sl_EfhxLZ9ck8
                count_on_hand: 25
                backorderable: false
                stock_location_id: sloc_gbHJdmfrXB
                variant_id: variant_gbHJdmfrXB
                external_references: {}
                metadata: {}
                reserved_count: 0
                incoming_count: 0
                purchasable_count: 25
                variant_name: Product 2169378
                variant_sku: SKU-267
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                stock_location_name: Gilbert Marquardt
                product_id: prod_UkLWZg9DAJ
                options_text: 'Size: S'
                thumbnail_url:
                allocated_count: 0
                available_count: 25
              schema:
                "$ref": "#/components/schemas/StockLevel"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/StockLevelUpdateParams"
        required: true
  "/api/v3/admin/stock_movements":
    get:
      summary: List stock movements
      tags:
      - Stock Movements
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the stock ledger, newest first. Every row says what happened to
        stock (`kind`) and carries a direct reference to what caused it, so a
        merchant can answer "why is this number what it is?" from the data.

        Kinds are `received` (goods arrived), `allocated` (stock promised to a
        placed order), `shipped` (promised stock left), `released` (a promise
        withdrawn) and `adjusted` (a manual correction, which always carries a
        `reason`).

        Movements are immutable — reversing one means writing its counterpart
        through the resource that caused it, which is why there is no create,
        update or delete here.

        Filter with Ransack predicates such as `q[kind_eq]`,
        `q[stock_level_id_eq]`, `q[order_id_eq]`, `q[fulfillment_id_eq]` or
        `q[created_at_gteq]`.

        `kind` is null on rows written before Spree 6.0 until
        `spree:migrate_stock_movements_to_typed_rows` has run.


        **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: stockMovements } = await client.stockMovements.list({
            kind_eq: 'allocated',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /stock_movements -d '{"kind_eq":"allocated"}'
      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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: fields
        in: query
        required: false
        description: Comma-separated list of fields to include. id is always included.
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[reason_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `exchange_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `fulfillment_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `kind` | One of `received`, `allocated`, `shipped`, `released`, `adjusted` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `order_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `purchase_order_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `quantity` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `reason` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `return_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `stock_level_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `stock_receipt_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `stock_transfer_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `unit_cost` | Amount | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[stock_level_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `stock_level_` | `allocated_count`, `count_on_hand`, `created_at`, `id`, `incoming_count`, `reserved_count`, `stock_location_id`, `updated_at`, `variant_id` |
          | `stock_level_stock_location_` | `active`, `country_code`, `created_at`, `default`, `id`, `kind`, `name`, `pickup_enabled`, `returns_enabled`, `seller_id`, `state_code`, `updated_at` |
          | `stock_level_variant_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |

          </Accordion>

          **Sort by:** `created_at`, `exchange_id`, `fulfillment_id`, `id`, `kind`, `order_id`, `purchase_order_id`, `quantity`, `reason`, `return_id`, `stock_level_id`, `stock_receipt_id`, `stock_transfer_id`, `unit_cost`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: StockMovement
        sortable:
        - created_at
        - exchange_id
        - fulfillment_id
        - id
        - kind
        - order_id
        - purchase_order_id
        - quantity
        - reason
        - return_id
        - stock_item_id
        - stock_level_id
        - stock_receipt_id
        - stock_transfer_id
        - unit_cost
        - updated_at
      responses:
        '200':
          description: stock movements found
          content:
            application/json:
              example:
                data:
                - id: sm_UkLWZg9DAJ
                  quantity: 5
                  kind: adjusted
                  reason: Cycle count
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  stock_level_id: sl_gbHJdmfrXB
                  stock_location_id: sloc_UkLWZg9DAJ
                  stock_location_name: Mona Hegmann
                  variant_id: variant_gbHJdmfrXB
                  variant_name: Product 2178513
                  variant_sku: SKU-268
                  order_id:
                  fulfillment_id:
                  return_id:
                  exchange_id:
                  stock_transfer_id:
                  stock_receipt_id:
                  purchase_order_id:
                  order_number:
                  return_number:
                  exchange_number:
                  stock_transfer_number:
                  purchase_order_number:
                  unit_cost:
                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/StockMovement"
                  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/stock_movements/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Stock movement ID
      schema:
        type: string
    get:
      summary: Get a stock movement
      tags:
      - Stock Movements
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns a single stock movement 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 stockMovement = await client.stockMovements.get('sm_k5nR8xLq')
      - lang: bash
        label: Spree CLI
        source: spree api get /stock_movements/{id}
      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 movement found
          content:
            application/json:
              example:
                id: sm_UkLWZg9DAJ
                quantity: 5
                kind: adjusted
                reason: Cycle count
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                stock_level_id: sl_gbHJdmfrXB
                stock_location_id: sloc_UkLWZg9DAJ
                stock_location_name: Chrystal Sauer
                variant_id: variant_gbHJdmfrXB
                variant_name: Product 2192954
                variant_sku: SKU-272
                order_id:
                fulfillment_id:
                return_id:
                exchange_id:
                stock_transfer_id:
                stock_receipt_id:
                purchase_order_id:
                order_number:
                return_number:
                exchange_number:
                stock_transfer_number:
                purchase_order_number:
                unit_cost:
              schema:
                "$ref": "#/components/schemas/StockMovement"
        '404':
          description: stock movement not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Stock movement not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
  "/api/v3/admin/stock_reservations":
    get:
      summary: List stock reservations
      tags:
      - Stock
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Returns the stock held for orders that are being checked out, so it cannot be sold twice before they complete or the hold expires.

        **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',
          })

          // Stock held for checkouts in progress, soonest to expire first.
          const { data: reservations } = await client.stockReservations.list({
            sort: 'expires_at',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /stock_reservations -d '{"sort":"expires_at"}'
      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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[created_at_eq]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `expires_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `line_item_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `order_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `quantity` | Number | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `stock_level_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[line_item_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `line_item_` | `additional_tax_total`, `adjustment_total`, `cost_price`, `created_at`, `discount_total`, `id`, `included_tax_total`, `non_taxable_adjustment_total`, `order_id`, `pre_tax_amount`, `price`, `quantity`, `tax_category_id`, `taxable_adjustment_total`, `updated_at`, `variant_id` |
          | `line_item_order_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `line_item_tax_category_` | `created_at`, `id`, `is_default`, `name`, `tax_code`, `updated_at` |
          | `line_item_variant_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `order_` | `channel_id`, `completed_at`, `considered_risky`, `coupon_code`, `created_at`, `currency`, `customer_id`, `delivery_total`, `email`, `fulfillment_status`, `id`, `item_total`, `locale`, `market_id`, `number`, `order_group_id`, `payment_status`, `po_number`, `seller_id`, `status`, `total`, `total_quantity`, `updated_at` |
          | `order_bill_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_channel_` | `active`, `code`, `created_at`, `default`, `id`, `name`, `store_id`, `updated_at` |
          | `order_customer_` | `accepts_email_marketing`, `created_at`, `email`, `first_name`, `id`, `last_name`, `phone`, `updated_at` |
          | `order_fulfillments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_line_items_` | `additional_tax_total`, `adjustment_total`, `cost_price`, `created_at`, `discount_total`, `id`, `included_tax_total`, `non_taxable_adjustment_total`, `order_id`, `pre_tax_amount`, `price`, `quantity`, `tax_category_id`, `taxable_adjustment_total`, `updated_at`, `variant_id` |
          | `order_order_group_` | `created_at`, `currency`, `email`, `id`, `number`, `updated_at` |
          | `order_promotions_` | `code`, `created_at`, `expires_at`, `id`, `kind`, `name`, `path`, `promotion_category_id`, `starts_at`, `updated_at` |
          | `order_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `order_ship_address_` | `address1`, `address2`, `city`, `company`, `country_code`, `created_at`, `first_name`, `id`, `last_name`, `phone`, `postal_code`, `state_code`, `updated_at` |
          | `order_shipments_` | `created_at`, `id`, `number`, `updated_at` |
          | `order_store_` | `created_at`, `id`, `name`, `updated_at` |
          | `order_tags_` | `created_at`, `id`, `name`, `updated_at` |
          | `stock_level_` | `allocated_count`, `count_on_hand`, `created_at`, `id`, `incoming_count`, `reserved_count`, `stock_location_id`, `updated_at`, `variant_id` |
          | `stock_level_stock_location_` | `active`, `country_code`, `created_at`, `default`, `id`, `kind`, `name`, `pickup_enabled`, `returns_enabled`, `seller_id`, `state_code`, `updated_at` |
          | `stock_level_variant_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |

          </Accordion>

          **Sort by:** `created_at`, `expires_at`, `id`, `line_item_id`, `order_id`, `quantity`, `stock_level_id`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: StockReservation
        sortable:
        - created_at
        - expires_at
        - id
        - line_item_id
        - order_id
        - quantity
        - stock_item_id
        - stock_level_id
        - updated_at
      responses:
        '200':
          description: stock reservations found
          content:
            application/json:
              example:
                data:
                - id: res_UkLWZg9DAJ
                  stock_level_id: sl_UkLWZg9DAJ
                  line_item_id: li_UkLWZg9DAJ
                  order_id: or_UkLWZg9DAJ
                  variant_id: variant_UkLWZg9DAJ
                  stock_location_id: sloc_UkLWZg9DAJ
                  quantity: 1
                  expires_at: '2026-01-15T12:10:00.000Z'
                  active: true
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                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/StockReservation"
                  meta:
                    "$ref": "#/components/schemas/PaginationMeta"
                required:
                - data
                - meta
  "/api/v3/admin/stock_transfers":
    get:
      summary: List stock transfers
      tags:
      - Stock Transfers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Stock moving between two of the merchant's own warehouses.

        A transfer is a trip, not an instant. Units leave the source when the
        transfer is marked in transit and land at the destination when somebody
        counts them in — in between they are in flight, gone from one shelf and
        not yet on the other.

        Statuses are `draft`, `ready_to_ship`, `in_transit`,
        `partially_received`, `received`, `over_received` and `canceled`. Each move between them
        is its own endpoint, not a `PATCH` that writes `status`.

        Receiving from a supplier is a purchase order, not a transfer with a
        missing source.

        Filter with Ransack predicates such as `q[status_eq]`,
        `q[source_location_id_eq]` or `q[number_or_reference_cont]`. Expand
        `items`, `source_location` and `destination_location`.


        **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: transfers } = await client.stockTransfers.list({
            open: true,
            sort: '-created_at',
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /stock_transfers -d '{"open":true,"sort":"-created_at"}'
      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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of number and reference (partial, case-insensitive).
      - name: q[closed]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `closed`.
      - name: q[open]
        in: query
        required: false
        schema:
          type: boolean
        description: Set to `true` to apply `open`.
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      - name: expand
        in: query
        required: false
        description: 'Comma-separated associations to embed: items, source_location,
          destination_location'
        schema:
          type: string
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `closed_short_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `destination_location_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `received_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `reference` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `shipped_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `source_location_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `status` | One of `draft`, `ready_to_ship`, `in_transit`, `partially_received`, `received`, `over_received`, `canceled` | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          <Accordion title="Filters through associations">

          Prefix an associated record's attribute with the association, as in `q[destination_location_id_eq]`. The same predicates apply.

          | Prefix | Attributes |
          |---|---|
          | `destination_location_` | `active`, `country_code`, `created_at`, `default`, `id`, `kind`, `name`, `pickup_enabled`, `returns_enabled`, `seller_id`, `state_code`, `updated_at` |
          | `destination_location_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |
          | `items_` | `created_at`, `id`, `quantity_received`, `quantity_rejected`, `quantity_shipped`, `updated_at`, `variant_id` |
          | `items_variant_` | `carton_package_type_id`, `carton_weight`, `cartons_per_pallet`, `cost_currency`, `cost_price`, `country_of_origin`, `created_at`, `deleted_at`, `depth`, `discontinue_on`, `height`, `hs_code`, `id`, `minimum_order_quantity`, `order_multiple`, `position`, `product_id`, `purchase_unit`, `sku`, `track_inventory`, `units_per_carton`, `updated_at`, `weight`, `width` |
          | `source_location_` | `active`, `country_code`, `created_at`, `default`, `id`, `kind`, `name`, `pickup_enabled`, `returns_enabled`, `seller_id`, `state_code`, `updated_at` |
          | `source_location_seller_` | `contact_email`, `created_at`, `id`, `name`, `status`, `updated_at` |

          </Accordion>

          **Sort by:** `closed_short_at`, `created_at`, `destination_location_id`, `id`, `number`, `received_at`, `reference`, `shipped_at`, `source_location_id`, `status`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: StockTransfer
        sortable:
        - closed_short_at
        - created_at
        - destination_location_id
        - id
        - number
        - received_at
        - reference
        - shipped_at
        - source_location_id
        - status
        - updated_at
      responses:
        '200':
          description: stock transfers found
          content:
            application/json:
              example:
                data:
                - id: st_UkLWZg9DAJ
                  number: T1001
                  reference: Weekly restock
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  source_location_id: sloc_UkLWZg9DAJ
                  destination_location_id: sloc_gbHJdmfrXB
                  status: draft
                  notes:
                  metadata: {}
                  close_reason:
                  items_count: 1
                  quantity_received_total: 0
                  quantity_rejected_total: 0
                  shipped_at:
                  received_at:
                  closed_short_at:
                  deleted_at:
                  closed_short: false
                  quantity_shipped_total: 10
                  editable: true
                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/StockTransfer"
                  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 transfer
      tags:
      - Stock Transfers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Persists a draft — a packing list the merchant can still edit. Nothing
        moves until the transfer is marked in transit.

        A draft may legitimately open empty and gain lines as the merchant
        packs. Both warehouses are required and must belong to the same store.


        **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',
          })

          // A draft: nothing moves until the transfer is marked in transit.
          const stockTransfer = await client.stockTransfers.create({
            source_location_id: 'sloc_1234567890',
            destination_location_id: 'sloc_0987654321',
            reference: 'Weekly restock',
            items: [{ variant_id: 'variant_1234567890', quantity_shipped: 10 }],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /stock_transfers -d '{"source_location_id":"sloc_1234567890","destination_location_id":"sloc_0987654321","reference":"Weekly
          restock","items":[{"variant_id":"variant_1234567890","quantity_shipped":10}]}'
      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 transfer created
          content:
            application/json:
              example:
                id: st_gbHJdmfrXB
                number: T1002
                reference: Weekly restock
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                source_location_id: sloc_UkLWZg9DAJ
                destination_location_id: sloc_gbHJdmfrXB
                status: draft
                notes:
                metadata: {}
                close_reason:
                items_count: 1
                quantity_received_total: 0
                quantity_rejected_total: 0
                shipped_at:
                received_at:
                closed_short_at:
                deleted_at:
                closed_short: false
                quantity_shipped_total: 10
                editable: true
              schema:
                "$ref": "#/components/schemas/StockTransfer"
        '404':
          description: warehouse belongs to another store
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Stock location not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/StockTransferCreateParams"
        required: true
  "/api/v3/admin/stock_transfers/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Stock transfer ID
      schema:
        type: string
    get:
      summary: Get a stock transfer
      tags:
      - Stock Transfers
      security:
      - api_key: []
        bearer_auth: []
      description: "**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 transfer = await client.stockTransfers.get('st_1234567890', {
            expand: ['items'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /stock_transfers/{id} -d '{"expand":["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: expand
        in: query
        required: false
        description: 'Comma-separated associations to embed: items, source_location,
          destination_location'
        schema:
          type: string
      responses:
        '200':
          description: stock transfer found
          content:
            application/json:
              example:
                id: st_UkLWZg9DAJ
                number: T1001
                reference: Weekly restock
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                source_location_id: sloc_UkLWZg9DAJ
                destination_location_id: sloc_gbHJdmfrXB
                status: draft
                notes:
                metadata: {}
                close_reason:
                items_count: 1
                quantity_received_total: 0
                quantity_rejected_total: 0
                shipped_at:
                received_at:
                closed_short_at:
                deleted_at:
                closed_short: false
                quantity_shipped_total: 10
                editable: true
                items:
                - id: sti_UkLWZg9DAJ
                  quantity_shipped: 10
                  quantity_received: 0
                  quantity_rejected: 0
                  quantity_over: 0
                  outstanding: 10
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  stock_transfer_id: st_UkLWZg9DAJ
                  variant_id: variant_gbHJdmfrXB
                  product_id: prod_UkLWZg9DAJ
                  variant_name: Product 2262176
                  variant_sku: SKU-285
                  options_text: 'Size: S'
                  thumbnail_url:
                source_location:
                  id: sloc_UkLWZg9DAJ
                  name: Warehouse
                  address1: 1600 Pennsylvania Ave NW
                  city: Washington
                  zipcode: '20500'
                  country_code: US
                  country_name: United States
                  state_code: AL
                  state_text: AL
                  pickup_ready_in_minutes:
                  pickup_instructions:
                  external_references: {}
                  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
                  returns_enabled: true
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  seller_id:
                  seller_name:
                destination_location:
                  id: sloc_gbHJdmfrXB
                  name: Brooklyn shop
                  address1: 1600 Pennsylvania Ave NW
                  city: Washington
                  zipcode: '20500'
                  country_code: US
                  country_name: United States
                  state_code: AL
                  state_text: AL
                  pickup_ready_in_minutes:
                  pickup_instructions:
                  external_references: {}
                  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
                  returns_enabled: true
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  seller_id:
                  seller_name:
              schema:
                "$ref": "#/components/schemas/StockTransfer"
        '404':
          description: stock transfer not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Stock transfer not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update a stock transfer
      tags:
      - Stock Transfers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Edits a draft: its reference, notes, either end, and its lines.
        Sending `items` replaces every line the draft holds. Status moves
        through the transfer's own actions, never through this endpoint.


        **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',
          })

          // Drafts only. Sending `items` replaces every line on the transfer.
          const transfer = await client.stockTransfers.update('st_1234567890', {
            reference: 'Restock east coast',
            items: [{ variant_id: 'variant_1234567890', quantity_shipped: 24 }],
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /stock_transfers/{id} -d '{"reference":"Restock east
          coast","items":[{"variant_id":"variant_1234567890","quantity_shipped":24}]}'
      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 transfer updated
          content:
            application/json:
              example:
                id: st_UkLWZg9DAJ
                number: T1001
                reference: Weekend restock
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                source_location_id: sloc_UkLWZg9DAJ
                destination_location_id: sloc_gbHJdmfrXB
                status: draft
                notes: Two cartons, fragile
                metadata: {}
                close_reason:
                items_count: 1
                quantity_received_total: 0
                quantity_rejected_total: 0
                shipped_at:
                received_at:
                closed_short_at:
                deleted_at:
                closed_short: false
                quantity_shipped_total: 12
                editable: true
              schema:
                "$ref": "#/components/schemas/StockTransfer"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/StockTransferUpdateParams"
        required: true
    delete:
      summary: Delete a stock transfer
      tags:
      - Stock Transfers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Drafts only. Past `draft` the transfer describes a box that physically
        exists, so it is cancelled rather than deleted — a 422 says so.


        **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',
          })

          // Drafts only: a transfer that has shipped is cancelled instead.
          await client.stockTransfers.delete('st_1234567890')
      - lang: bash
        label: Spree CLI
        source: spree api delete /stock_transfers/{id}
      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 transfer deleted
  "/api/v3/admin/stock_transfers/{id}/mark_ready":
    parameters:
    - name: id
      in: path
      required: true
      description: Stock transfer ID
      schema:
        type: string
    patch:
      summary: Mark a transfer ready to ship
      tags:
      - Stock Transfers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Freezes the lines so the warehouse and the merchant are looking at the
        same list. Nothing leaves the shelf yet.


        **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',
          })

          // Freezes the lines; nothing leaves the source shelf until the transfer is sent.
          const transfer = await client.stockTransfers.markReady('st_1234567890')
      - lang: bash
        label: Spree CLI
        source: spree api patch /stock_transfers/{id}/mark_ready -d '{ ... }'
      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: transfer is ready to ship
          content:
            application/json:
              example:
                id: st_UkLWZg9DAJ
                number: T1001
                reference: Weekly restock
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                source_location_id: sloc_UkLWZg9DAJ
                destination_location_id: sloc_gbHJdmfrXB
                status: ready_to_ship
                notes:
                metadata: {}
                close_reason:
                items_count: 1
                quantity_received_total: 0
                quantity_rejected_total: 0
                shipped_at:
                received_at:
                closed_short_at:
                deleted_at:
                closed_short: false
                quantity_shipped_total: 10
                editable: false
              schema:
                "$ref": "#/components/schemas/StockTransfer"
  "/api/v3/admin/stock_transfers/{id}/mark_in_transit":
    parameters:
    - name: id
      in: path
      required: true
      description: Stock transfer ID
      schema:
        type: string
    patch:
      summary: Send a transfer
      tags:
      - Stock Transfers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        The moment stock leaves the source warehouse: `shipped` movements are
        written against the source's levels and `shipped_at` is stamped. The
        destination is deliberately untouched — the units are in flight.

        Refused with a 422 when the source does not hold enough. Pass
        `force: true` to record the departure anyway: a merchant forcing it has
        decided the box left whatever the ledger claims.


        **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',
          })

          // The units leave the source warehouse here.
          const stockTransfer = await client.stockTransfers.markInTransit('st_1234567890')
      - lang: bash
        label: Spree CLI
        source: spree api patch /stock_transfers/{id}/mark_in_transit -d '{ ... }'
      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: transfer is in transit
          content:
            application/json:
              example:
                id: st_UkLWZg9DAJ
                number: T1001
                reference: Weekly restock
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                source_location_id: sloc_UkLWZg9DAJ
                destination_location_id: sloc_gbHJdmfrXB
                status: in_transit
                notes:
                metadata: {}
                close_reason:
                items_count: 1
                quantity_received_total: 0
                quantity_rejected_total: 0
                shipped_at: '2026-01-15T12:00:00.000Z'
                received_at:
                closed_short_at:
                deleted_at:
                closed_short: false
                quantity_shipped_total: 10
                editable: false
              schema:
                "$ref": "#/components/schemas/StockTransfer"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/StockTransferMarkInTransitParams"
        required: true
  "/api/v3/admin/stock_transfers/{stock_transfer_id}/stock_receipts":
    parameters:
    - name: stock_transfer_id
      in: path
      required: true
      description: Stock transfer ID
      schema:
        type: string
    get:
      summary: List the deliveries counted in against a transfer
      tags:
      - Stock Transfers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Each delivery the destination counted in, with what it accepted and refused.

        **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',
          })

          // Every delivery the destination counted in.
          const { data: stockReceipts } = await client.stockTransfers.stockReceipts.list('st_1234567890', {
            expand: ['items'],
          })
      - lang: bash
        label: Spree CLI
        source: spree api get /stock_transfers/{stock_transfer_id}/stock_receipts
          -d '{"expand":["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: q
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[number_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `number` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `receivable_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `receivable_type` | Type | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `received_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `received_by_id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `received_by_type` | Type | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `reference` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `created_at`, `id`, `number`, `receivable_id`, `receivable_type`, `received_at`, `received_by_id`, `received_by_type`, `reference`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: StockReceipt
        sortable:
        - created_at
        - id
        - number
        - receivable_id
        - receivable_type
        - received_at
        - received_by_id
        - received_by_type
        - reference
        - updated_at
      responses:
        '200':
          description: deliveries found
          content:
            application/json:
              example:
                data:
                - id: sr_UkLWZg9DAJ
                  number: SR1001
                  reference:
                  notes:
                  metadata: {}
                  quantity_accepted_total: 8
                  quantity_rejected_total: 0
                  received_at: '2026-01-15T12:00:00.000Z'
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  receivable_type: stock_transfer
                  receivable_id: st_UkLWZg9DAJ
                  received_by_id:
                  received_by_type:
                  items_count: 1
                meta:
                  page: 1
                  limit: 25
                  count: 1
                  pages: 1
                  from: 1
                  to: 1
                  in: 1
                  previous:
                  next:
    post:
      summary: Count a delivery in
      tags:
      - Stock Transfers
      operationId: stock_transfers_receive
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Records one delivery the destination warehouse counted in, as a stock
        receipt. Partial receipt is the normal case: ten left, eight arrived,
        two were crushed in transit. Quantities are this delivery's counts —
        a second box adds to the first rather than restating it.

        `quantity_accepted` lands on the destination's shelf;
        `quantity_rejected` is refused and recorded with a `rejection_reason`
        (`damaged`, `wrong_item`, `expired` or `other`), never stocked. A
        refused unit still arrived, so it counts toward the trip being over.
        Omit `items` to count in everything still outstanding, intact.

        The transfer stays `partially_received` while units are still on the
        road, settles in `received` once everything has arrived, and in
        `over_received` once more arrived than was shipped.


        **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',
          })

          // Partial receipt is the normal case: ten left, eight arrived intact and two
          // crushed. Refused units are recorded, never stocked.
          const stockReceipt = await client.stockTransfers.stockReceipts.create('st_1234567890', {
            items: [
              {
                id: 'sti_1234567890',
                quantity_accepted: 8,
                quantity_rejected: 2,
                rejection_reason: 'damaged',
              },
            ],
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /stock_transfers/{stock_transfer_id}/stock_receipts
          -d '{"items":[{"id":"sti_1234567890","quantity_accepted":8,"quantity_rejected":2,"rejection_reason":"damaged"}]}'
      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: delivery counted in
          content:
            application/json:
              example:
                id: sr_UkLWZg9DAJ
                number: SR1001
                reference:
                notes:
                metadata: {}
                quantity_accepted_total: 8
                quantity_rejected_total: 2
                received_at: '2026-01-15T12:00:00.000Z'
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                receivable_type: stock_transfer
                receivable_id: st_UkLWZg9DAJ
                received_by_id: adm_UkLWZg9DAJ
                received_by_type: admin_user
                items_count: 1
              schema:
                "$ref": "#/components/schemas/StockReceipt"
        '422':
          description: transfer has not shipped yet
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: Only a transfer in transit can be received
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/StockReceiptCreateParams"
        required: true
  "/api/v3/admin/stock_transfers/{id}/mark_draft":
    parameters:
    - name: id
      in: path
      required: true
      description: Stock transfer ID
      schema:
        type: string
    patch:
      summary: Take a transfer back to draft
      tags:
      - Stock Transfers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Unfreezes a ready-to-ship transfer so its lines can be changed. Nothing has left the source, so nothing is undone.

        **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',
          })

          // Nothing has left the source yet, so the lines can be changed again.
          const stockTransfer = await client.stockTransfers.markDraft('st_1234567890')
      - lang: bash
        label: Spree CLI
        source: spree api patch /stock_transfers/{id}/mark_draft -d '{ ... }'
      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: transfer back in draft
          content:
            application/json:
              example:
                id: st_UkLWZg9DAJ
                number: T1001
                reference: Weekly restock
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                source_location_id: sloc_UkLWZg9DAJ
                destination_location_id: sloc_gbHJdmfrXB
                status: draft
                notes:
                metadata: {}
                close_reason:
                items_count: 1
                quantity_received_total: 0
                quantity_rejected_total: 0
                shipped_at:
                received_at:
                closed_short_at:
                deleted_at:
                closed_short: false
                quantity_shipped_total: 10
                editable: true
              schema:
                "$ref": "#/components/schemas/StockTransfer"
  "/api/v3/admin/stock_transfers/{id}/close":
    parameters:
    - name: id
      in: path
      required: true
      description: Stock transfer ID
      schema:
        type: string
    patch:
      summary: Close a transfer short
      tags:
      - Stock Transfers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Ends a partially received transfer whose missing units are not going
        to turn up. Nothing moves — they already left the source — and the
        transfer settles in `received` with `closed_short_at` and the
        `reason` recorded, the outstanding count left on each line.


        **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',
          })

          // The missing units are not going to turn up: keep what arrived, record why.
          const stockTransfer = await client.stockTransfers.close('st_1234567890', {
            reason: 'Two fell off the van',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /stock_transfers/{id}/close -d '{"reason":"Two fell
          off the van"}'
      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: transfer closed short
          content:
            application/json:
              example:
                id: st_UkLWZg9DAJ
                number: T1001
                reference: Weekly restock
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                source_location_id: sloc_UkLWZg9DAJ
                destination_location_id: sloc_gbHJdmfrXB
                status: received
                notes:
                metadata: {}
                close_reason: Two fell off the van
                items_count: 1
                quantity_received_total: 8
                quantity_rejected_total: 0
                shipped_at: '2026-01-15T12:00:00.000Z'
                received_at: '2026-01-15T12:00:00.000Z'
                closed_short_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                closed_short: true
                quantity_shipped_total: 10
                editable: false
              schema:
                "$ref": "#/components/schemas/StockTransfer"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/ReceivableCloseParams"
        required: true
  "/api/v3/admin/stock_transfers/{id}/cancel":
    parameters:
    - name: id
      in: path
      required: true
      description: Stock transfer ID
      schema:
        type: string
    patch:
      summary: Cancel a stock transfer
      tags:
      - Stock Transfers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Calls the trip off.

        Cancelling a draft or a packed transfer costs nothing — no stock has
        moved. Cancelling one already in transit needs `on_in_transit`, because
        the units are physically gone from the source: either they come back
        (`restock`, as if the transfer had never shipped) or they are written
        off as lost (`write_off`). There is no default — guessing would either
        invent stock or destroy it — so an in-flight cancellation without it is
        refused with a 422.


        **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',
          })

          // Once units have left the source, say whether they come back or are written off.
          const transfer = await client.stockTransfers.cancel('st_1234567890', {
            on_in_transit: 'write_off',
            reason: 'Lost in transit',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /stock_transfers/{id}/cancel -d '{"on_in_transit":"write_off","reason":"Lost
          in transit"}'
      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: transfer cancelled
          content:
            application/json:
              example:
                id: st_UkLWZg9DAJ
                number: T1001
                reference: Weekly restock
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                source_location_id: sloc_UkLWZg9DAJ
                destination_location_id: sloc_gbHJdmfrXB
                status: canceled
                notes:
                metadata: {}
                close_reason:
                items_count: 1
                quantity_received_total: 0
                quantity_rejected_total: 0
                shipped_at: '2026-01-15T12:00:00.000Z'
                received_at:
                closed_short_at:
                deleted_at:
                closed_short: false
                quantity_shipped_total: 10
                editable: false
              schema:
                "$ref": "#/components/schemas/StockTransfer"
        '422':
          description: in-transit cancellation needs a decision
          content:
            application/json:
              example:
                error:
                  code: processing_error
                  message: Choose whether the units come back to the source warehouse
                    or are written off
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/StockTransferCancelParams"
        required: true
  "/api/v3/admin/suppliers":
    get:
      summary: List suppliers
      tags:
      - Suppliers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Who the merchant buys stock from. A supplier is an address-book entry
        with a purchasing history — not a party that sells on the store, which
        is a seller.

        Suppliers belong to one store, and are soft-deleted so the purchase
        orders that name them stay readable.

        Filter with Ransack predicates such as
        `q[name_or_contact_name_or_email_cont]` or `q[country_code_eq]`.


        **Required scope:** `read_purchasing` (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: suppliers } = await client.suppliers.list({ search: 'Acme' })
      - lang: bash
        label: Spree CLI
        source: spree api get /suppliers -d '{"search":"Acme"}'
      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: q[search]
        in: query
        required: false
        schema:
          type: string
        description: Matches any of name, contact name, and email (partial, case-insensitive).
      - 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
        in: query
        required: false
        style: deepObject
        explode: true
        schema:
          type: object
          additionalProperties: true
        description: Attribute filters, as `q[<attribute>_<predicate>]=value`. See
          Filters above for the list.
      x-mint:
        content: |-
          ## Filters

          Filter with `q[<attribute>_<predicate>]=value`, for example `q[name_cont]=…`. Send a list as `q[<attribute>_in][]=a&q[<attribute>_in][]=b`. [How filters work](/api-reference/admin-api/querying#which-filters-an-endpoint-accepts).

          | Attribute | Kind | Predicates |
          |---|---|---|
          | `city` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `contact_name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `country_code` | One of the `CountryCode` codes | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `created_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |
          | `email` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `id` | Prefixed ID | `eq` `not_eq` `in` `not_in` `null` `not_null` |
          | `name` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `phone` | Text | `eq` `not_eq` `in` `not_in` `cont` `i_cont` `not_cont` `start` `end` `null` `not_null` `present` `blank` |
          | `updated_at` | Date and time | `eq` `not_eq` `in` `not_in` `lt` `lteq` `gt` `gteq` `null` `not_null` |

          **Sort by:** `city`, `contact_name`, `country_code`, `created_at`, `email`, `id`, `name`, `phone`, `updated_at`. Prefix a field with `-` to sort descending.
      x-spree-filters:
        table: Supplier
        sortable:
        - city
        - contact_name
        - country_code
        - created_at
        - email
        - id
        - name
        - phone
        - updated_at
      responses:
        '200':
          description: suppliers found
          content:
            application/json:
              example:
                data:
                - id: sup_UkLWZg9DAJ
                  name: Acme Wholesale
                  contact_name: Dana Okafor
                  email: supplier17@example.com
                  phone: 555-0100
                  notes:
                  address1: 1 Warehouse Way
                  address2:
                  city: Brooklyn
                  state_name:
                  state_code: NY
                  country_code: US
                  postal_code: '11201'
                  purchase_orders_count: 0
                  metadata: {}
                  created_at: '2026-01-15T12:00:00.000Z'
                  updated_at: '2026-01-15T12:00:00.000Z'
                  deleted_at:
                  can_be_deleted: true
                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/Supplier"
                  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 supplier
      tags:
      - Suppliers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Adds a supplier to this store's address book. The address is inline —
        street, city, state and country live on the supplier itself, the same
        shape a stock location uses.


        **Required scope:** `write_purchasing` (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 supplier = await client.suppliers.create({
            name: 'Acme Wholesale',
            contact_name: 'Dana Okafor',
            email: 'sales@acme.test',
            city: 'Brooklyn',
            country_code: 'US',
          })
      - lang: bash
        label: Spree CLI
        source: spree api post /suppliers -d '{"name":"Acme Wholesale","contact_name":"Dana
          Okafor","email":"sales@acme.test","city":"Brooklyn","country_code":"US"}'
      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: supplier created
          content:
            application/json:
              example:
                id: sup_gbHJdmfrXB
                name: Northwind Trading
                contact_name: Dana Okafor
                email: sales@northwind.test
                phone:
                notes:
                address1:
                address2:
                city: Brooklyn
                state_name:
                state_code:
                country_code: US
                postal_code:
                purchase_orders_count: 0
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                can_be_deleted: true
              schema:
                "$ref": "#/components/schemas/Supplier"
        '422':
          description: validation error
          content:
            application/json:
              example:
                error:
                  code: validation_error
                  message: Name can't be blank
                  details:
                    name:
                    - code: blank
                      message: can't be blank
                      specific: false
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SupplierCreateParams"
        required: true
  "/api/v3/admin/suppliers/{id}":
    parameters:
    - name: id
      in: path
      required: true
      description: Supplier ID
      schema:
        type: string
    get:
      summary: Get a supplier
      tags:
      - Suppliers
      security:
      - api_key: []
        bearer_auth: []
      description: "**Required scope:** `read_purchasing` (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 supplier = await client.suppliers.get('sup_1234567890')
      - lang: bash
        label: Spree CLI
        source: spree api get /suppliers/{id}
      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: supplier found
          content:
            application/json:
              example:
                id: sup_UkLWZg9DAJ
                name: Acme Wholesale
                contact_name: Dana Okafor
                email: supplier21@example.com
                phone: 555-0100
                notes:
                address1: 1 Warehouse Way
                address2:
                city: Brooklyn
                state_name:
                state_code: NY
                country_code: US
                postal_code: '11201'
                purchase_orders_count: 0
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                can_be_deleted: true
              schema:
                "$ref": "#/components/schemas/Supplier"
        '404':
          description: supplier not found
          content:
            application/json:
              example:
                error:
                  code: record_not_found
                  message: Supplier not found
              schema:
                "$ref": "#/components/schemas/ErrorResponse"
    patch:
      summary: Update a supplier
      tags:
      - Suppliers
      security:
      - api_key: []
        bearer_auth: []
      description: "**Required scope:** `write_purchasing` (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 supplier = await client.suppliers.update('sup_1234567890', {
            contact_name: 'Jordan Lee',
            email: 'orders@acme-supply.com',
            phone: '+1 555 0100',
          })
      - lang: bash
        label: Spree CLI
        source: spree api patch /suppliers/{id} -d '{"contact_name":"Jordan Lee","email":"orders@acme-supply.com","phone":"+1
          555 0100"}'
      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: supplier updated
          content:
            application/json:
              example:
                id: sup_UkLWZg9DAJ
                name: Acme Wholesale
                contact_name: Sam Reyes
                email: supplier23@example.com
                phone: 555-0100
                notes:
                address1: 1 Warehouse Way
                address2:
                city: Brooklyn
                state_name:
                state_code: NY
                country_code: US
                postal_code: '11201'
                purchase_orders_count: 0
                metadata: {}
                created_at: '2026-01-15T12:00:00.000Z'
                updated_at: '2026-01-15T12:00:00.000Z'
                deleted_at:
                can_be_deleted: true
              schema:
                "$ref": "#/components/schemas/Supplier"
      requestBody:
        content:
          application/json:
            schema:
              "$ref": "#/components/schemas/SupplierUpdateParams"
        required: true
    delete:
      summary: Delete a supplier
      tags:
      - Suppliers
      security:
      - api_key: []
        bearer_auth: []
      description: |-
        Soft-deletes the supplier, so the purchase orders naming it stay
        readable. Refused with a 422 while a purchase order still points at it.


        **Required scope:** `write_purchasing` (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.suppliers.delete('sup_1234567890')
      - lang: bash
        label: Spree CLI
        source: spree api delete /suppliers/{id}
      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: supplier deleted
  "/api/v3/oauth/protected-resource/{resource_key}":
    parameters:
    - name: resource_key
      in: path
      required: true
      description: Which protected surface, e.g. `mcp`
      schema:
        type: string
    get:
      summary: Discover the authorization server
      tags:
      - OAuth
      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 response = await fetch('https://your-store.com/api/v3/oauth/protected-resource/admin')
          const metadata = await response.json()
      - lang: bash
        label: Spree CLI
        source: spree api get /api/v3/oauth/protected-resource/{resource_key}
      description: |
        RFC 9728. A client given a URL it cannot reach unauthenticated reads
        this to learn which authorization server guards it and which
        permissions that server accepts.

        Unauthenticated by design: a client has to read it before it holds
        anything.
      responses:
        '200':
          description: metadata
          content:
            application/json:
              example:
                resource: http://www.example.com/api/v3/admin/mcp
                authorization_servers:
                - http://www.example.com
                scopes_supported:
                - read_dashboard
                - read_reports
                - write_reports
                - read_orders
                - write_orders
                - read_payments
                - write_payments
                - read_fulfillments
                - write_fulfillments
                - read_refunds
                - write_refunds
                - read_products
                - write_products
                - read_product_types
                - write_product_types
                - read_publishing
                - write_publishing
                - read_media
                - write_media
                - read_categories
                - write_categories
                - read_collections
                - write_collections
                - read_stock
                - write_stock
                - read_purchasing
                - write_purchasing
                - read_customers
                - write_customers
                - read_sellers
                - write_sellers
                - read_commissions
                - write_commissions
                - read_payouts
                - write_payouts
                - read_gift_cards
                - write_gift_cards
                - read_store_credits
                - write_store_credits
                - read_promotions
                - write_promotions
                - read_settings
                - write_settings
                - read_delivery_methods
                - write_delivery_methods
                - read_package_types
                - write_package_types
                - read_email_templates
                - write_email_templates
                - read_maintenance_tasks
                - write_maintenance_tasks
                bearer_methods_supported:
                - header
                resource_documentation: https://spreecommerce.org/docs/developer/mcp/overview
              schema:
                "$ref": "#/components/schemas/OauthProtectedResource"
        '404':
          description: no such protected surface
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: Categories
  description: Hierarchical product categories — tree management, repositioning, and
    product assignments
- name: Channels
  description: Sales channels, product publication across channels, and per-channel
    order routing rules
- 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: Email Templates
  description: 'Customer email templates, the email layout and shared partials: drafts,
    previews, publishing and history'
- name: Exports
  description: Async CSV exports of admin resources
- name: Files
  description: Uploading the files that product media, imports, logos and documents
    use
- name: Fulfillments
  description: Order fulfillments — shipments, fulfill, cancel, resume, split
- name: Gift Cards
  description: Gift cards and gift card batches
- name: Imports
  description: Async CSV imports of admin resources, with per-row status and failed-row
    retry
- name: Maintenance Tasks
  description: Operator-run data work — backfills, reindexes and upgrade steps — and
    the record of every run
- 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: Policies
  description: The store's legal documents — terms of service, privacy, returns, shipping
- name: Reasons
  description: Merchant-owned vocabularies for why a return, claim, refund, cancellation
    or tax exemption happened
- 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, and configuration
- name: Staff
  description: Admin users, roles, and invitations to the store
- name: Stock Locations
  description: Warehouses and physical fulfillment locations
- name: Store Credits
  description: Prepaid customer balances across all customers, and each balance's
    ledger
- name: Variants
  description: Product variants — the individual SKUs (size/color combinations) sold
    under a product
- name: Webhooks
  description: Webhook endpoints and webhook delivery history
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 short names, e.g. ["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
    ImportSchemaField:
      type: object
      description: A canonical column of an import type, including per-store custom
        field columns
      properties:
        name:
          type: string
          description: Canonical field name used in mappings
          example: slug
        label:
          type: string
          description: Human-readable label
          example: Slug
        required:
          type: boolean
          description: Whether the field must be mapped before processing
      required:
      - name
      - label
      - required
    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
        item_index:
          type: integer
          nullable: true
          description: Position in the submitted items array, for warnings raised
            while applying a batch of item changes
          example: 1
      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
    AdminUserStore:
      type: object
      description: A store the staff member can access through a role assignment
      properties:
        id:
          type: string
          description: Prefixed store ID
          example: store_abc123
        name:
          type: string
          description: Store name
          example: My Store
        code:
          type: string
          description: Store code
          example: my-store
      required:
      - id
      - name
      - code
    PreferenceSchema:
      type: object
      description: 'The JSON Schema (draft 2020-12) of a type''s `preferences`: one
        property per setting, with `format` (`money`, `currency`, `iso-country`, `prefixed-id`,
        …), `enum`, `default`, `x-spree-secret` for a secret and `x-spree-prefix`
        for an id list. Unknown keys are refused.'
      additionalProperties: true
      example:
        type: object
        properties:
          amount:
            type: string
            format: money
            default: '0.0'
        additionalProperties: false
    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
    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
    Actor:
      type: object
      properties:
        id:
          type: string
        type:
          anyOf:
          - type: string
            enum:
            - admin_user
            - api_key
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        label:
          type: string
          nullable: true
      required:
      - id
      - type
      - label
      x-typelizer: true
    AddressOwner:
      type: object
      properties:
        id:
          type: string
        type:
          anyOf:
          - type: string
            enum:
            - customer
            - company
            - seller
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        name:
          type: string
          nullable: true
      required:
      - id
      - type
      - name
      x-typelizer: true
    Address:
      type: object
      properties:
        id:
          type: string
        label:
          type: string
          nullable: true
        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_code:
          type: string
          enum:
          - AD
          - AE
          - AF
          - AG
          - AI
          - AL
          - AM
          - AO
          - AR
          - AS
          - AT
          - AU
          - AW
          - AZ
          - BA
          - BB
          - BD
          - BE
          - BF
          - BG
          - BH
          - BI
          - BJ
          - BL
          - BM
          - BN
          - BO
          - BQ
          - BR
          - BS
          - BT
          - BW
          - BY
          - BZ
          - CA
          - CC
          - CD
          - CF
          - CG
          - CH
          - CI
          - CK
          - CL
          - CM
          - CN
          - CO
          - CR
          - CU
          - CV
          - CW
          - CX
          - CY
          - CZ
          - DE
          - DJ
          - DK
          - DM
          - DO
          - DZ
          - EC
          - EE
          - EG
          - ER
          - ES
          - ET
          - FI
          - FJ
          - FK
          - FM
          - FO
          - FR
          - GA
          - GB
          - GD
          - GE
          - GF
          - GG
          - GH
          - GI
          - GL
          - GM
          - GN
          - GP
          - GQ
          - GR
          - GT
          - GU
          - GW
          - GY
          - HK
          - HN
          - HR
          - HT
          - HU
          - ID
          - IE
          - IL
          - IM
          - IN
          - IQ
          - IR
          - IS
          - IT
          - JE
          - JM
          - JO
          - JP
          - KE
          - KG
          - KH
          - KI
          - KM
          - KN
          - KP
          - KR
          - KW
          - KY
          - KZ
          - LA
          - LB
          - LC
          - LI
          - LK
          - LR
          - LS
          - LT
          - LU
          - LV
          - LY
          - MA
          - MC
          - MD
          - ME
          - MF
          - MG
          - MH
          - MK
          - ML
          - MM
          - MN
          - MO
          - MP
          - MQ
          - MR
          - MS
          - MT
          - MU
          - MV
          - MW
          - MX
          - MY
          - MZ
          - NA
          - NC
          - NE
          - NF
          - NG
          - NI
          - NL
          - 'NO'
          - NP
          - NR
          - NU
          - NZ
          - OM
          - PA
          - PE
          - PF
          - PG
          - PH
          - PK
          - PL
          - PM
          - PN
          - PR
          - PS
          - PT
          - PW
          - PY
          - QA
          - RE
          - RO
          - RS
          - RU
          - RW
          - SA
          - SB
          - SC
          - SD
          - SE
          - SG
          - SH
          - SI
          - SJ
          - SK
          - SL
          - SM
          - SN
          - SO
          - SR
          - SS
          - ST
          - SV
          - SX
          - SY
          - SZ
          - TC
          - TD
          - TG
          - TH
          - TJ
          - TK
          - TL
          - TM
          - TN
          - TO
          - TR
          - TT
          - TV
          - TW
          - TZ
          - UA
          - UG
          - US
          - UY
          - UZ
          - VA
          - VC
          - VE
          - VG
          - VI
          - VN
          - VU
          - WF
          - WS
          - YE
          - YT
          - ZA
          - ZM
          - ZW
        state_text:
          type: string
          nullable: true
        state_code:
          type: string
          nullable: true
        quick_checkout:
          type: boolean
        is_default_billing:
          type: boolean
        is_default_shipping:
          type: boolean
        state_name:
          type: string
          nullable: true
        owner:
          allOf:
          - "$ref": "#/components/schemas/AddressOwner"
          nullable: true
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        metadata:
          type: object
        created_at:
          type: string
        updated_at:
          type: string
        latitude:
          type: number
          nullable: true
        longitude:
          type: number
          nullable: true
        customer_id:
          type: string
          nullable: true
      required:
      - id
      - label
      - first_name
      - last_name
      - full_name
      - address1
      - address2
      - postal_code
      - city
      - phone
      - company
      - country_name
      - country_code
      - state_text
      - state_code
      - quick_checkout
      - is_default_billing
      - is_default_shipping
      - state_name
      - owner
      - metadata
      - created_at
      - updated_at
      - latitude
      - longitude
      - customer_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
        selected_locale:
          type: string
          nullable: true
        status:
          type: string
          enum:
          - active
          - locked
          - deactivated
        created_at:
          type: string
        updated_at:
          type: string
        last_active_at:
          type: string
          nullable: true
        sessions:
          type: array
          items:
            "$ref": "#/components/schemas/Session"
        inviter:
          allOf:
          - "$ref": "#/components/schemas/Actor"
          nullable: true
        avatar_url:
          type: string
          nullable: true
        roles:
          type: array
          items:
            "$ref": "#/components/schemas/AdminUserRoleAssignment"
        stores:
          type: array
          items:
            "$ref": "#/components/schemas/AdminUserStore"
      required:
      - id
      - email
      - first_name
      - last_name
      - full_name
      - selected_locale
      - status
      - created_at
      - updated_at
      - last_active_at
      - avatar_url
      - roles
      - stores
      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
          enum:
          - publishable
          - secret
        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
        channel_id:
          type: string
          nullable: true
        plaintext_token:
          type: string
          nullable: true
        created_by_email:
          type: string
          nullable: true
        created_by_type:
          anyOf:
          - type: string
            enum:
            - admin_user
            - api_key
          - type: string
            nullable: true
          description: The values listed are the built-in ones; extensions may add
            more.
        created_by_label:
          type: string
          nullable: true
      required:
      - id
      - name
      - key_type
      - token_prefix
      - scopes
      - created_at
      - updated_at
      - revoked_at
      - last_used_at
      - channel_id
      - plaintext_token
      - created_by_email
      - created_by_type
      - created_by_label
      x-typelizer: true
    AppliedPromotion:
      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
        created_at:
          type: string
        updated_at:
          type: string
      required:
      - id
      - promotion_id
      - name
      - description
      - code
      - amount
      - created_at
      - updated_at
      x-typelizer: true
    Cart:
      type: object
      properties:
        id:
          type: string
        market_id:
          type: string
          nullable: true
        channel_id:
          type: string
          nullable: true
        preferred_stock_location_id:
          type: string
          nullable: true
        company_id:
          type: string
          nullable: true
        company_name:
          type: string
          nullable: true
        po_number_required:
          type: boolean
        po_document_filename:
          type: string
          nullable: true
        po_document_byte_size:
          type: number
          nullable: true
        token:
          type: string
        email:
          type: string
          nullable: true
        customer_note:
          type: string
          nullable: true
        po_number:
          type: string
          nullable: true
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        locale:
          type: string
          nullable: true
          enum:
          - aa
          - ab
          - ae
          - af
          - ak
          - am
          - an
          - ar
          - as
          - av
          - ay
          - az
          - ba
          - be
          - bg
          - bh
          - bi
          - bm
          - bn
          - bo
          - br
          - bs
          - ca
          - ce
          - ch
          - co
          - cr
          - cs
          - cu
          - cv
          - cy
          - da
          - de
          - de-AT
          - de-CH
          - dv
          - dz
          - ee
          - el
          - en
          - en-AU
          - en-CA
          - en-GB
          - en-IN
          - en-NZ
          - en-US
          - eo
          - es
          - es-419
          - es-CL
          - es-EC
          - es-MX
          - et
          - eu
          - fa
          - ff
          - fi
          - fj
          - fo
          - fr
          - fr-CA
          - fy
          - ga
          - gd
          - gl
          - gn
          - gu
          - gv
          - ha
          - he
          - hi
          - ho
          - hr
          - ht
          - hu
          - hy
          - hz
          - ia
          - id
          - ie
          - ig
          - ii
          - ik
          - io
          - is
          - it
          - iu
          - ja
          - jv
          - ka
          - kg
          - ki
          - kj
          - kk
          - kl
          - km
          - kn
          - ko
          - kr
          - ks
          - ku
          - kv
          - kw
          - ky
          - la
          - lb
          - lg
          - li
          - ln
          - lo
          - lt
          - lu
          - lv
          - mg
          - mh
          - mi
          - mk
          - ml
          - mn
          - mr
          - ms
          - mt
          - my
          - na
          - nb
          - nd
          - ne
          - ng
          - nl
          - nn
          - 'no'
          - nr
          - nv
          - ny
          - oc
          - oj
          - om
          - or
          - os
          - pa
          - pi
          - pl
          - ps
          - pt
          - pt-BR
          - pt-PT
          - qu
          - rm
          - rn
          - ro
          - ru
          - rw
          - sa
          - sc
          - sd
          - se
          - sg
          - si
          - sk
          - sl
          - sl-SI
          - sm
          - sn
          - so
          - sq
          - sr
          - ss
          - st
          - su
          - sv
          - sw
          - ta
          - te
          - tg
          - th
          - ti
          - tk
          - tl
          - tn
          - to
          - tr
          - ts
          - tt
          - tw
          - ty
          - ug
          - uk
          - ur
          - uz
          - ve
          - vi
          - vo
          - wa
          - wo
          - xh
          - yi
          - yo
          - za
          - zh-CN
          - zh-HK
          - zh-TW
          - zu
        total_quantity:
          type: number
        warnings:
          type: array
          items:
            "$ref": "#/components/schemas/CartWarning"
        coupon_code:
          type: string
          nullable: true
        item_total:
          type: string
          nullable: true
          description: 'The line items: each price times its quantity, before discounts,
            fees and delivery.'
        discount_total:
          type: string
          nullable: true
          description: What promotions take off, as a negative amount. Manual discounts
            are not included.
        tax_total:
          type: string
          nullable: true
          description: All tax, both included in prices and added on top.
        included_tax_total:
          type: string
          nullable: true
          description: Tax already included in the prices, as in a store whose prices
            are tax-inclusive.
        additional_tax_total:
          type: string
          nullable: true
          description: Tax added on top of the prices.
        delivery_total:
          type: string
          nullable: true
          description: What delivery costs, before delivery discounts.
        fee_total:
          type: string
          nullable: true
          description: Every fee charged, such as handling or a customs duty.
        gift_card_total:
          type: string
          nullable: true
          description: What a gift card pays.
        store_credit_total:
          type: string
          nullable: true
          description: What store credit pays, apart from gift cards.
        total:
          type: string
          nullable: true
          description: 'What the customer pays in all: items, delivery, fees and added
            tax, less discounts.'
        amount_due:
          type: string
          nullable: true
          description: What is left to pay after payments and store credit.
        covered_by_store_credit:
          type: boolean
        adjustment_total:
          type: string
          nullable: true
          description: Every discount, fee and added tax together, as one amount.
        current_step:
          type: string
        completed_steps:
          type: array
          items:
            type: string
        requirements:
          type: array
          items:
            "$ref": "#/components/schemas/CheckoutRequirement"
        order_minimum:
          type: string
          nullable: true
        order_minimum_shortfall:
          type: string
          nullable: true
        below_order_minimum:
          type: boolean
          nullable: true
        freight_summary:
          allOf:
          - "$ref": "#/components/schemas/FreightSummary"
          nullable: true
        shipping_eq_billing_address:
          type: boolean
        items:
          type: array
          items:
            "$ref": "#/components/schemas/LineItem"
        billing_address:
          allOf:
          - "$ref": "#/components/schemas/Address"
          nullable: true
        shipping_address:
          allOf:
          - "$ref": "#/components/schemas/Address"
          nullable: true
        market:
          allOf:
          - "$ref": "#/components/schemas/Market"
          nullable: true
        completed_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        applied_promotions:
          type: array
          items:
            "$ref": "#/components/schemas/AppliedPromotion"
      required:
      - id
      - market_id
      - channel_id
      - preferred_stock_location_id
      - company_id
      - company_name
      - po_number_required
      - po_document_filename
      - po_document_byte_size
      - token
      - email
      - customer_note
      - po_number
      - currency
      - locale
      - total_quantity
      - warnings
      - coupon_code
      - item_total
      - discount_total
      - tax_total
      - included_tax_total
      - additional_tax_total
      - delivery_total
      - fee_total
      - gift_card_total
      - store_credit_total
      - total
      - amount_due
      - covered_by_store_credit
      - adjustment_total
      - current_step
      - completed_steps
      - requirements
      - order_minimum
      - order_minimum_shortfall
      - below_order_minimum
      - freight_summary
      - shipping_eq_billing_address
      - items
      - billing_address
      - shipping_address
      - market
      - completed_at
      - created_at
      - updated_at
      - applied_promotions
      x-typelizer: true
    CatalogAssignment:
      type: object
      properties:
        id:
          type: string
        created_at:
          type: string
        catalog_id:
          type: string
        assignable_type:
          type: string
          enum:
          - customer_group
          - company
        assignable_id:
          type: string
        assignable_name:
          type: string
          nullable: true
      required:
      - id
      - created_at
      - catalog_id
      - assignable_type
      - assignable_id
      - assignable_name
      x-typelizer: true
    CatalogOrderMinimum:
      type: object
      properties:
        id:
          type: string
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        created_at:
          type: string
        updated_at:
          type: string
        amount:
          type: string
      required:
      - id
      - currency
      - created_at
      - updated_at
      - amount
      x-typelizer: true
    CatalogPrice:
      type: object
      properties:
        id:
          type: string
          nullable: true
        label:
          type: string
          nullable: true
        sku:
          type: string
          nullable: true
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        source:
          type: string
          enum:
          - explicit
          - automatic
          - base
        break_count:
          type: number
        amount:
          type: string
        tiers:
          type: array
          items:
            "$ref": "#/components/schemas/CatalogPriceTier"
      required:
      - id
      - label
      - sku
      - currency
      - source
      - break_count
      - amount
      - tiers
      x-typelizer: true
    CatalogPriceTier:
      type: object
      properties:
        min_quantity:
          type: number
        amount:
          type: string
      required:
      - min_quantity
      - amount
      x-typelizer: true
    CatalogProduct:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        thumbnail_url:
          type: string
          nullable: true
        quantity_rule:
          allOf:
          - "$ref": "#/components/schemas/CatalogProductTerm"
          nullable: true
        catalog_variants:
          type: array
          items:
            "$ref": "#/components/schemas/CatalogPrice"
      required:
      - id
      - name
      - thumbnail_url
      x-typelizer: true
    CatalogProductTerm:
      type: object
      properties:
        id:
          type: string
        product_id:
          type: string
        product_name:
          type: string
          nullable: true
        minimum_order_quantity:
          type: number
          nullable: true
        order_multiple:
          type: number
          nullable: true
        mixed:
          type: boolean
      required:
      - id
      - product_id
      - product_name
      - minimum_order_quantity
      - order_multiple
      - mixed
      x-typelizer: true
    CatalogQuantityRule:
      type: object
      properties:
        id:
          type: string
        minimum_order_quantity:
          type: number
          nullable: true
        order_multiple:
          type: number
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        variant_id:
          type: string
          nullable: true
        variant_sku:
          type: string
          nullable: true
        product_name:
          type: string
          nullable: true
        options_text:
          type: string
          nullable: true
      required:
      - id
      - minimum_order_quantity
      - order_multiple
      - created_at
      - updated_at
      - variant_id
      - variant_sku
      - product_name
      - options_text
      x-typelizer: true
    Catalog:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
          nullable: true
        active:
          type: boolean
        position:
          type: number
          nullable: true
        metadata:
          type: object
          nullable: true
        minimum_order_quantity:
          type: number
          nullable: true
        order_multiple:
          type: number
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        products_count:
          type: number
        pricing_strategy:
          type: string
        order_minimums:
          type: array
          items:
            "$ref": "#/components/schemas/CatalogOrderMinimum"
        price_list:
          "$ref": "#/components/schemas/PriceList"
        assignments:
          type: array
          items:
            "$ref": "#/components/schemas/CatalogAssignment"
      required:
      - id
      - name
      - description
      - active
      - position
      - metadata
      - minimum_order_quantity
      - order_multiple
      - created_at
      - updated_at
      - products_count
      - pricing_strategy
      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"
        external_references:
          type: object
        translations:
          type: object
        metadata:
          type: object
        pretty_name:
          type: string
        lft:
          type: number
        rgt:
          type: number
        products_count:
          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
      - external_references
      - metadata
      - pretty_name
      - lft
      - rgt
      - products_count
      - 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
        storefront_access:
          type: string
          nullable: true
          enum:
          - public
          - prices_hidden
          - login_required
        guest_checkout:
          type: boolean
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        order_routing_strategy:
          type: string
          nullable: true
          description: 'Order routing strategy; null inherits the store setting. Built-in:
            rules. Extensions may register more.'
        stock_location_ids:
          type: array
          items:
            type: string
        default_catalog_id:
          type: string
          nullable: true
      required:
      - id
      - name
      - code
      - active
      - default
      - storefront_access
      - guest_checkout
      - created_at
      - updated_at
      - order_routing_strategy
      - stock_location_ids
      - default_catalog_id
      x-typelizer: true
    ClaimLineItem:
      type: object
      properties:
        id:
          type: string
        quantity:
          type: number
        send_replacement:
          type: boolean
        description:
          type: string
          nullable: true
        refund_amount:
          type: string
        paid_amount:
          type: string
        pre_tax_amount:
          type: string
        included_tax_total:
          type: string
        additional_tax_total:
          type: string
        tax_total:
          type: string
        variant_id:
          type: string
          nullable: true
        replacement_variant_id:
          type: string
          nullable: true
        line_item_id:
          type: string
          nullable: true
        variant:
          "$ref": "#/components/schemas/Variant"
        created_at:
          type: string
        updated_at:
          type: string
        replacement_variant:
          "$ref": "#/components/schemas/Variant"
      required:
      - id
      - quantity
      - send_replacement
      - description
      - refund_amount
      - paid_amount
      - pre_tax_amount
      - included_tax_total
      - additional_tax_total
      - tax_total
      - variant_id
      - replacement_variant_id
      - line_item_id
      - created_at
      - updated_at
      x-typelizer: true
    ClaimReason:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        active:
          type: boolean
        created_at:
          type: string
        updated_at:
          type: string
        can_be_deleted:
          type: boolean
      required:
      - id
      - name
      - active
      - created_at
      - updated_at
      - can_be_deleted
      x-typelizer: true
    Claim:
      type: object
      properties:
        id:
          type: string
        number:
          type: string
        status:
          anyOf:
          - type: string
            enum:
            - open
            - approved
            - resolved
            - denied
            - canceled
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        resolution:
          type: string
          nullable: true
          enum:
          - refund
          - replacement
          - refund_and_replacement
        order_id:
          type: string
          nullable: true
        reason_id:
          type: string
          nullable: true
        refund_total:
          type: string
        approved_at:
          type: string
          nullable: true
        resolved_at:
          type: string
          nullable: true
        denied_at:
          type: string
          nullable: true
        canceled_at:
          type: string
          nullable: true
        reason:
          "$ref": "#/components/schemas/ClaimReason"
        claim_line_items:
          type: array
          items:
            "$ref": "#/components/schemas/ClaimLineItem"
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        memo:
          type: string
          nullable: true
        metadata:
          type: object
        created_at:
          type: string
        updated_at:
          type: string
        created_by_id:
          type: string
          nullable: true
        created_by_type:
          anyOf:
          - type: string
            enum:
            - admin_user
            - api_key
          - type: string
            nullable: true
          description: The values listed are the built-in ones; extensions may add
            more.
        created_by:
          "$ref": "#/components/schemas/Actor"
        order:
          "$ref": "#/components/schemas/Order"
        refunds:
          type: array
          items:
            "$ref": "#/components/schemas/Refund"
      required:
      - id
      - number
      - status
      - resolution
      - order_id
      - reason_id
      - refund_total
      - approved_at
      - resolved_at
      - denied_at
      - canceled_at
      - memo
      - metadata
      - created_at
      - updated_at
      - created_by_id
      - created_by_type
      x-typelizer: true
    CollectionRule:
      type: object
      properties:
        id:
          type: string
        value:
          type: string
          nullable: true
        match_policy:
          type: string
          enum:
          - is_equal_to
          - is_not_equal_to
          - contains
          - does_not_contain
        type:
          type: string
          description: 'Rule type. Built-in: tag, available_on, sale. Extensions may
            register more.'
      required:
      - id
      - value
      - match_policy
      - type
      x-typelizer: true
    Collection:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        permalink:
          type: string
        position:
          type: number
        sort_order:
          type: string
          enum:
          - manual
          - best_selling
          - price asc
          - price desc
          - available_on desc
          - available_on asc
          - name asc
          - name desc
        meta_title:
          type: string
          nullable: true
        meta_description:
          type: string
          nullable: true
        meta_keywords:
          type: string
          nullable: true
        products_count:
          type: number
        description:
          type: string
        description_html:
          type: string
        image_url:
          type: string
          nullable: true
        square_image_url:
          type: string
          nullable: true
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        translations:
          type: object
        automatic:
          type: boolean
        rules_match_policy:
          type: string
          enum:
          - all
          - any
        metadata:
          type: object
        created_at:
          type: string
        updated_at:
          type: string
        rules:
          type: array
          items:
            "$ref": "#/components/schemas/CollectionRule"
      required:
      - id
      - name
      - permalink
      - position
      - sort_order
      - meta_title
      - meta_description
      - meta_keywords
      - products_count
      - description
      - description_html
      - image_url
      - square_image_url
      - automatic
      - rules_match_policy
      - metadata
      - created_at
      - updated_at
      x-typelizer: true
    CommissionLine:
      type: object
      properties:
        id:
          type: string
        kind:
          type: string
          enum:
          - percentage
          - fixed
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        taxability_reason:
          anyOf:
          - type: string
            enum:
            - standard_rated
            - reduced_rated
            - zero_rated
            - reverse_charge
            - intra_community_supply
            - export
            - customer_exempt
            - product_exempt
            - not_collecting
            - not_subject_to_tax
          - type: string
            nullable: true
          description: The values listed are the built-in ones; extensions may add
            more.
        country_code:
          type: string
          nullable: true
          enum:
          - AD
          - AE
          - AF
          - AG
          - AI
          - AL
          - AM
          - AO
          - AR
          - AS
          - AT
          - AU
          - AW
          - AZ
          - BA
          - BB
          - BD
          - BE
          - BF
          - BG
          - BH
          - BI
          - BJ
          - BL
          - BM
          - BN
          - BO
          - BQ
          - BR
          - BS
          - BT
          - BW
          - BY
          - BZ
          - CA
          - CC
          - CD
          - CF
          - CG
          - CH
          - CI
          - CK
          - CL
          - CM
          - CN
          - CO
          - CR
          - CU
          - CV
          - CW
          - CX
          - CY
          - CZ
          - DE
          - DJ
          - DK
          - DM
          - DO
          - DZ
          - EC
          - EE
          - EG
          - ER
          - ES
          - ET
          - FI
          - FJ
          - FK
          - FM
          - FO
          - FR
          - GA
          - GB
          - GD
          - GE
          - GF
          - GG
          - GH
          - GI
          - GL
          - GM
          - GN
          - GP
          - GQ
          - GR
          - GT
          - GU
          - GW
          - GY
          - HK
          - HN
          - HR
          - HT
          - HU
          - ID
          - IE
          - IL
          - IM
          - IN
          - IQ
          - IR
          - IS
          - IT
          - JE
          - JM
          - JO
          - JP
          - KE
          - KG
          - KH
          - KI
          - KM
          - KN
          - KP
          - KR
          - KW
          - KY
          - KZ
          - LA
          - LB
          - LC
          - LI
          - LK
          - LR
          - LS
          - LT
          - LU
          - LV
          - LY
          - MA
          - MC
          - MD
          - ME
          - MF
          - MG
          - MH
          - MK
          - ML
          - MM
          - MN
          - MO
          - MP
          - MQ
          - MR
          - MS
          - MT
          - MU
          - MV
          - MW
          - MX
          - MY
          - MZ
          - NA
          - NC
          - NE
          - NF
          - NG
          - NI
          - NL
          - 'NO'
          - NP
          - NR
          - NU
          - NZ
          - OM
          - PA
          - PE
          - PF
          - PG
          - PH
          - PK
          - PL
          - PM
          - PN
          - PR
          - PS
          - PT
          - PW
          - PY
          - QA
          - RE
          - RO
          - RS
          - RU
          - RW
          - SA
          - SB
          - SC
          - SD
          - SE
          - SG
          - SH
          - SI
          - SJ
          - SK
          - SL
          - SM
          - SN
          - SO
          - SR
          - SS
          - ST
          - SV
          - SX
          - SY
          - SZ
          - TC
          - TD
          - TG
          - TH
          - TJ
          - TK
          - TL
          - TM
          - TN
          - TO
          - TR
          - TT
          - TV
          - TW
          - TZ
          - UA
          - UG
          - US
          - UY
          - UZ
          - VA
          - VC
          - VE
          - VG
          - VI
          - VN
          - VU
          - WF
          - WS
          - YE
          - YT
          - ZA
          - ZM
          - ZW
        state_code:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        rate:
          type: string
        tax_rate:
          type: string
        amount:
          type: string
        tax_amount:
          type: string
        total:
          type: string
        order_id:
          type: string
        seller_id:
          type: string
        line_item_id:
          type: string
          nullable: true
        fulfillment_id:
          type: string
          nullable: true
        commission_rate_id:
          type: string
          nullable: true
        seller_name:
          type: string
          nullable: true
        commission_rate:
          "$ref": "#/components/schemas/CommissionRate"
      required:
      - id
      - kind
      - currency
      - taxability_reason
      - country_code
      - state_code
      - created_at
      - updated_at
      - rate
      - tax_rate
      - amount
      - tax_amount
      - total
      - order_id
      - seller_id
      - line_item_id
      - fulfillment_id
      - commission_rate_id
      - seller_name
      x-typelizer: true
    CommissionRate:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        code:
          type: string
          nullable: true
        enabled:
          type: boolean
        position:
          type: number
        kind:
          type: string
          enum:
          - percentage
          - fixed
        tax_inclusive:
          type: boolean
        include_shipping:
          type: boolean
        metadata:
          type: object
          nullable: true
        deleted_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        value:
          type: string
        commission_tax_rate:
          type: string
          nullable: true
        amounts:
          type: object
        bounds:
          type: object
        global:
          type: boolean
        rules:
          type: array
          items:
            "$ref": "#/components/schemas/CommissionRule"
      required:
      - id
      - name
      - code
      - enabled
      - position
      - kind
      - tax_inclusive
      - include_shipping
      - metadata
      - deleted_at
      - created_at
      - updated_at
      - value
      - commission_tax_rate
      - amounts
      - bounds
      - global
      - rules
      x-typelizer: true
    CommissionRule:
      type: object
      properties:
        id:
          type: string
        created_at:
          type: string
        updated_at:
          type: string
        type:
          type: string
          description: 'Rule type. Built-in: seller_rule, category_rule, product_rule,
            item_total_rule. Extensions may register more.'
        commission_rate_id:
          type: string
        preferences:
          "$ref": "#/components/schemas/CommissionRulePreferences"
        product_ids:
          type: array
          items:
            type: string
          nullable: true
        seller_ids:
          type: array
          items:
            type: string
          nullable: true
        category_ids:
          type: array
          items:
            type: string
          nullable: true
        sellers:
          type: array
          items:
            "$ref": "#/components/schemas/Seller"
        categories:
          type: array
          items:
            "$ref": "#/components/schemas/Category"
      required:
      - id
      - created_at
      - updated_at
      - type
      - commission_rate_id
      - preferences
      - product_ids
      - seller_ids
      - category_ids
      x-typelizer: true
    CompanyInvitation:
      type: object
      properties:
        id:
          type: string
        email:
          type: string
        expires_at:
          type: string
          nullable: true
        company_id:
          type: string
        status:
          type: string
          enum:
          - pending
          - accepted
          - revoked
          - expired
        accepted_at:
          type: string
          nullable: true
        revoked_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
      required:
      - id
      - email
      - expires_at
      - company_id
      - status
      - accepted_at
      - revoked_at
      - created_at
      - updated_at
      x-typelizer: true
    CompanyMembership:
      type: object
      properties:
        id:
          type: string
        company_id:
          type: string
        customer_id:
          type: string
        email:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        customer:
          "$ref": "#/components/schemas/Customer"
      required:
      - id
      - company_id
      - customer_id
      - email
      - created_at
      - updated_at
      x-typelizer: true
    Company:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        kind:
          type: string
          enum:
          - company
          - division
        po_number_required:
          type: boolean
        parent_id:
          type: string
          nullable: true
        ancestors:
          type: array
          items:
            type: object
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        external_references:
          type: object
        metadata:
          type: object
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        children_count:
          type: number
        members_count:
          type: number
        children:
          type: array
          items:
            "$ref": "#/components/schemas/Company"
        addresses:
          type: array
          items:
            "$ref": "#/components/schemas/Address"
        memberships:
          type: array
          items:
            "$ref": "#/components/schemas/CompanyMembership"
      required:
      - id
      - name
      - kind
      - po_number_required
      - parent_id
      - ancestors
      - external_references
      - metadata
      - created_at
      - updated_at
      - children_count
      - members_count
      x-typelizer: true
    ConsentRecord:
      type: object
      properties:
        id:
          type: string
        purpose:
          type: string
        source:
          type: string
          enum:
          - checkout
          - registration
          - account
          - admin
          - newsletter
          - anonymization
          - unknown
          - import
          - storefront
        accepted:
          type: boolean
        email:
          type: string
          nullable: true
        ip_address:
          type: string
          nullable: true
        created_at:
          type: string
        recorded_at:
          type: string
          nullable: true
        documents:
          type: array
          items:
            type: object
      required:
      - id
      - purpose
      - source
      - accepted
      - email
      - ip_address
      - created_at
      - recorded_at
      - documents
      x-typelizer: true
    Country:
      type: object
      properties:
        iso:
          type: string
          enum:
          - AD
          - AE
          - AF
          - AG
          - AI
          - AL
          - AM
          - AO
          - AR
          - AS
          - AT
          - AU
          - AW
          - AZ
          - BA
          - BB
          - BD
          - BE
          - BF
          - BG
          - BH
          - BI
          - BJ
          - BL
          - BM
          - BN
          - BO
          - BQ
          - BR
          - BS
          - BT
          - BW
          - BY
          - BZ
          - CA
          - CC
          - CD
          - CF
          - CG
          - CH
          - CI
          - CK
          - CL
          - CM
          - CN
          - CO
          - CR
          - CU
          - CV
          - CW
          - CX
          - CY
          - CZ
          - DE
          - DJ
          - DK
          - DM
          - DO
          - DZ
          - EC
          - EE
          - EG
          - ER
          - ES
          - ET
          - FI
          - FJ
          - FK
          - FM
          - FO
          - FR
          - GA
          - GB
          - GD
          - GE
          - GF
          - GG
          - GH
          - GI
          - GL
          - GM
          - GN
          - GP
          - GQ
          - GR
          - GT
          - GU
          - GW
          - GY
          - HK
          - HN
          - HR
          - HT
          - HU
          - ID
          - IE
          - IL
          - IM
          - IN
          - IQ
          - IR
          - IS
          - IT
          - JE
          - JM
          - JO
          - JP
          - KE
          - KG
          - KH
          - KI
          - KM
          - KN
          - KP
          - KR
          - KW
          - KY
          - KZ
          - LA
          - LB
          - LC
          - LI
          - LK
          - LR
          - LS
          - LT
          - LU
          - LV
          - LY
          - MA
          - MC
          - MD
          - ME
          - MF
          - MG
          - MH
          - MK
          - ML
          - MM
          - MN
          - MO
          - MP
          - MQ
          - MR
          - MS
          - MT
          - MU
          - MV
          - MW
          - MX
          - MY
          - MZ
          - NA
          - NC
          - NE
          - NF
          - NG
          - NI
          - NL
          - 'NO'
          - NP
          - NR
          - NU
          - NZ
          - OM
          - PA
          - PE
          - PF
          - PG
          - PH
          - PK
          - PL
          - PM
          - PN
          - PR
          - PS
          - PT
          - PW
          - PY
          - QA
          - RE
          - RO
          - RS
          - RU
          - RW
          - SA
          - SB
          - SC
          - SD
          - SE
          - SG
          - SH
          - SI
          - SJ
          - SK
          - SL
          - SM
          - SN
          - SO
          - SR
          - SS
          - ST
          - SV
          - SX
          - SY
          - SZ
          - TC
          - TD
          - TG
          - TH
          - TJ
          - TK
          - TL
          - TM
          - TN
          - TO
          - TR
          - TT
          - TV
          - TW
          - TZ
          - UA
          - UG
          - US
          - UY
          - UZ
          - VA
          - VC
          - VE
          - VG
          - VI
          - VN
          - VU
          - WF
          - WS
          - YE
          - YT
          - ZA
          - ZM
          - ZW
        iso3:
          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
      required:
      - iso
      - iso3
      - states_required
      - zipcode_required
      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
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        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
        storefront_visible:
          type: boolean
        searchable:
          type: boolean
        sortable:
          type: boolean
        filter_key:
          type: string
        created_at:
          type: string
        updated_at:
          type: string
        resource_type:
          type: string
          description: Shorthand of the resource the field attaches to, for example
            product, variant, order, customer or category. Discover the full list
            from the resource_types endpoint; extensions may register more.
      required:
      - id
      - namespace
      - key
      - label
      - field_type
      - storefront_visible
      - searchable
      - sortable
      - filter_key
      - created_at
      - updated_at
      - resource_type
      x-typelizer: true
    CustomField:
      type: object
      properties:
        id:
          type: string
        label:
          type: string
        field_type:
          type: string
          enum:
          - short_text
          - long_text
          - rich_text
          - number
          - boolean
          - json
        key:
          type: string
        value: {}
        created_at:
          type: string
        updated_at:
          type: string
        storefront_visible:
          type: boolean
        custom_field_definition_id:
          type: string
      required:
      - id
      - label
      - 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
        email_marketing_consent_updated_at:
          type: string
          nullable: true
        full_name:
          type: string
        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
        newsletter_subscriber:
          allOf:
          - "$ref": "#/components/schemas/NewsletterSubscriber"
          nullable: true
        customer_groups:
          type: array
          items:
            "$ref": "#/components/schemas/CustomerGroup"
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        failed_attempts:
          type: number
        metadata:
          type: object
        email_marketing_consent_source:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        anonymized_at:
          type: string
          nullable: true
        anonymized:
          type: boolean
        tags:
          type: array
          items:
            type: string
        internal_note:
          type: string
          nullable: true
        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
        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_group_ids:
          type: array
          items:
            type: string
        companies:
          type: array
          items:
            "$ref": "#/components/schemas/Company"
      required:
      - id
      - email
      - first_name
      - last_name
      - phone
      - accepts_email_marketing
      - email_marketing_consent_updated_at
      - full_name
      - available_store_credit_total
      - failed_attempts
      - metadata
      - email_marketing_consent_source
      - created_at
      - updated_at
      - anonymized_at
      - anonymized
      - tags
      - internal_note
      - internal_note_html
      - default_billing_address_id
      - default_shipping_address_id
      - orders_count
      - total_spent
      - last_order_completed_at
      - customer_group_ids
      x-typelizer: true
    DashboardCounter:
      type: object
      properties:
        key:
          type: string
          description: 'Registered counter name. The dashboard translates it; built-in:
            orders_to_fulfill, payments_to_collect, open_returns, open_exchanges,
            open_claims, low_stock_items, out_of_stock_items.'
        value:
          type: number
        link:
          type: object
          nullable: true
          description: The list filter that shows exactly the rows counted, or null
            when no list can.
        nav:
          type: string
          nullable: true
          description: Sidebar entry key this count badges, or null.
      required:
      - key
      - value
      - link
      - nav
      x-typelizer: true
    DataRequest:
      type: object
      properties:
        id:
          type: string
        number:
          type: string
        kind:
          type: string
          enum:
          - access
          - erasure
        status:
          anyOf:
          - type: string
            enum:
            - awaiting_confirmation
            - pending
            - processing
            - completed
            - failed
            - lapsed
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        requested_at:
          type: string
          nullable: true
        completed_at:
          type: string
          nullable: true
        expires_at:
          type: string
          nullable: true
        email:
          type: string
        error_message:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        customer_id:
          type: string
          nullable: true
        requested_by_id:
          type: string
          nullable: true
        customer:
          "$ref": "#/components/schemas/Customer"
      required:
      - id
      - number
      - kind
      - status
      - requested_at
      - completed_at
      - expires_at
      - email
      - error_message
      - created_at
      - updated_at
      - customer_id
      - requested_by_id
      x-typelizer: true
    DeliveryMethodRule:
      type: object
      properties:
        id:
          type: string
        active:
          type: boolean
        created_at:
          type: string
        updated_at:
          type: string
        type:
          type: string
          description: 'Rule type. Built-in: item_total_rule, weight_rule, excluded_products_rule,
            channel_rule, volume_rule, company_rule. Extensions may register more.'
        preferences:
          "$ref": "#/components/schemas/DeliveryMethodRulePreferences"
        product_ids:
          type: array
          items:
            type: string
      required:
      - id
      - active
      - created_at
      - updated_at
      - type
      - preferences
      - product_ids
      x-typelizer: true
    DeliveryMethod:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        code:
          type: string
          nullable: true
        estimated_transit_business_days_min:
          type: number
          nullable: true
        estimated_transit_business_days_max:
          type: number
          nullable: true
        digital:
          type: boolean
        pickup:
          type: boolean
        pickup_point:
          type: boolean
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        admin_name:
          type: string
          nullable: true
        storefront_visible:
          type: boolean
        tracking_url:
          type: string
          nullable: true
        available_to_sellers:
          type: boolean
        created_at:
          type: string
        updated_at:
          type: string
        deleted_at:
          type: string
        markup_flat:
          type: string
          nullable: true
        markup_percent:
          type: string
          nullable: true
        seller_id:
          type: string
          nullable: true
        seller_name:
          type: string
          nullable: true
        services:
          type: array
          items:
            "$ref": "#/components/schemas/DeliveryMethodService"
        rules:
          type: array
          items:
            "$ref": "#/components/schemas/DeliveryMethodRule"
        tax_category_id:
          type: string
          nullable: true
        delivery_profile_id:
          type: string
        delivery_origin_group_id:
          type: string
          nullable: true
        delivery_zone_id:
          type: string
          nullable: true
        stock_location_ids:
          type: array
          items:
            type: string
        fulfillment_provider:
          type: string
          description: 'Fulfillment provider. Built-in: manual, digital, pickup, pickup_point.
            Provider gems register more (e.g. easy_post).'
        pickup_point_provider:
          type: string
          nullable: true
          description: Pickup point network. None built in; provider gems register
            them.
        rate_provider:
          type: string
          nullable: true
          description: 'Rate provider; null prices through the calculator. Built-in:
            internal, freight. Provider gems register more (e.g. easy_post).'
        calculator:
          allOf:
          - "$ref": "#/components/schemas/DeliveryMethodCalculator"
          nullable: true
      required:
      - id
      - name
      - code
      - estimated_transit_business_days_min
      - estimated_transit_business_days_max
      - digital
      - pickup
      - pickup_point
      - admin_name
      - storefront_visible
      - tracking_url
      - available_to_sellers
      - created_at
      - updated_at
      - deleted_at
      - markup_flat
      - markup_percent
      - seller_id
      - seller_name
      - services
      - rules
      - tax_category_id
      - delivery_profile_id
      - delivery_origin_group_id
      - delivery_zone_id
      - stock_location_ids
      - fulfillment_provider
      - pickup_point_provider
      - rate_provider
      - calculator
      x-typelizer: true
    DeliveryMethodService:
      type: object
      properties:
        id:
          type: string
        carrier:
          type: string
        service:
          type: string
        label:
          type: string
          nullable: true
        markup_flat:
          type: string
          nullable: true
        markup_percent:
          type: string
          nullable: true
        position:
          type: number
      required:
      - id
      - carrier
      - service
      - label
      - markup_flat
      - markup_percent
      - position
      x-typelizer: true
    DeliveryOriginGroup:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
          nullable: true
        position:
          type: number
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        delivery_profile_id:
          type: string
        stock_location_ids:
          type: array
          items:
            type: string
        delivery_zones_count:
          type: number
        delivery_methods_count:
          type: number
      required:
      - id
      - name
      - position
      - created_at
      - updated_at
      - delivery_profile_id
      - stock_location_ids
      - delivery_zones_count
      - delivery_methods_count
      x-typelizer: true
    DeliveryProfile:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        default:
          type: boolean
        position:
          type: number
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        kind:
          type: string
          description: 'Profile kind. Built-in: shipping, digital. Extensions may
            register more.'
        digital:
          type: boolean
        offers_pickup:
          type: boolean
        offers_shipping:
          type: boolean
        stock_location_ids:
          type: array
          items:
            type: string
        origin_groups:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              name:
                type: string
                nullable: true
              position:
                type: number
                nullable: true
              stock_location_ids:
                type: array
                items:
                  type: string
            required:
            - id
            - name
            - position
            - stock_location_ids
        products_count:
          type: number
        delivery_methods_count:
          type: number
        delivery_zones_count:
          type: number
      required:
      - id
      - name
      - default
      - position
      - created_at
      - updated_at
      - kind
      - digital
      - offers_pickup
      - offers_shipping
      - stock_location_ids
      - origin_groups
      - products_count
      - delivery_methods_count
      - delivery_zones_count
      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
        carrier:
          type: string
          nullable: true
        service_level:
          type: string
          nullable: true
        estimated_delivery_date:
          type: string
          nullable: true
        unpriced:
          type: boolean
        freight_summary:
          allOf:
          - "$ref": "#/components/schemas/FreightSummary"
          nullable: true
        delivery_method:
          "$ref": "#/components/schemas/DeliveryMethod"
        metadata:
          type: object
          nullable: true
        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
      - carrier
      - service_level
      - estimated_delivery_date
      - unpriced
      - freight_summary
      - metadata
      - created_at
      - updated_at
      x-typelizer: true
    Delivery:
      type: object
      properties:
        id:
          type: string
        tracking_number:
          type: string
        carrier:
          type: string
          nullable: true
        carrier_name:
          type: string
          nullable: true
        service:
          type: string
          nullable: true
        status:
          type: string
          enum:
          - pending
          - pre_transit
          - in_transit
          - out_for_delivery
          - available_for_pickup
          - delivered
          - return_to_sender
          - failure
          - unknown
        tracking_url:
          type: string
          nullable: true
        estimated_delivery_at:
          type: string
          nullable: true
        delivered_at:
          type: string
          nullable: true
        details:
          type: object
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        shipping_label_id:
          type: string
          nullable: true
      required:
      - id
      - tracking_number
      - carrier
      - carrier_name
      - service
      - status
      - tracking_url
      - estimated_delivery_at
      - delivered_at
      - details
      - created_at
      - updated_at
      - shipping_label_id
      x-typelizer: true
    DeliveryZoneMember:
      type: object
      properties:
        id:
          type: string
        member_type:
          type: string
          enum:
          - country
          - state
          - postal_code
        country_code:
          type: string
          nullable: true
          enum:
          - AD
          - AE
          - AF
          - AG
          - AI
          - AL
          - AM
          - AO
          - AR
          - AS
          - AT
          - AU
          - AW
          - AZ
          - BA
          - BB
          - BD
          - BE
          - BF
          - BG
          - BH
          - BI
          - BJ
          - BL
          - BM
          - BN
          - BO
          - BQ
          - BR
          - BS
          - BT
          - BW
          - BY
          - BZ
          - CA
          - CC
          - CD
          - CF
          - CG
          - CH
          - CI
          - CK
          - CL
          - CM
          - CN
          - CO
          - CR
          - CU
          - CV
          - CW
          - CX
          - CY
          - CZ
          - DE
          - DJ
          - DK
          - DM
          - DO
          - DZ
          - EC
          - EE
          - EG
          - ER
          - ES
          - ET
          - FI
          - FJ
          - FK
          - FM
          - FO
          - FR
          - GA
          - GB
          - GD
          - GE
          - GF
          - GG
          - GH
          - GI
          - GL
          - GM
          - GN
          - GP
          - GQ
          - GR
          - GT
          - GU
          - GW
          - GY
          - HK
          - HN
          - HR
          - HT
          - HU
          - ID
          - IE
          - IL
          - IM
          - IN
          - IQ
          - IR
          - IS
          - IT
          - JE
          - JM
          - JO
          - JP
          - KE
          - KG
          - KH
          - KI
          - KM
          - KN
          - KP
          - KR
          - KW
          - KY
          - KZ
          - LA
          - LB
          - LC
          - LI
          - LK
          - LR
          - LS
          - LT
          - LU
          - LV
          - LY
          - MA
          - MC
          - MD
          - ME
          - MF
          - MG
          - MH
          - MK
          - ML
          - MM
          - MN
          - MO
          - MP
          - MQ
          - MR
          - MS
          - MT
          - MU
          - MV
          - MW
          - MX
          - MY
          - MZ
          - NA
          - NC
          - NE
          - NF
          - NG
          - NI
          - NL
          - 'NO'
          - NP
          - NR
          - NU
          - NZ
          - OM
          - PA
          - PE
          - PF
          - PG
          - PH
          - PK
          - PL
          - PM
          - PN
          - PR
          - PS
          - PT
          - PW
          - PY
          - QA
          - RE
          - RO
          - RS
          - RU
          - RW
          - SA
          - SB
          - SC
          - SD
          - SE
          - SG
          - SH
          - SI
          - SJ
          - SK
          - SL
          - SM
          - SN
          - SO
          - SR
          - SS
          - ST
          - SV
          - SX
          - SY
          - SZ
          - TC
          - TD
          - TG
          - TH
          - TJ
          - TK
          - TL
          - TM
          - TN
          - TO
          - TR
          - TT
          - TV
          - TW
          - TZ
          - UA
          - UG
          - US
          - UY
          - UZ
          - VA
          - VC
          - VE
          - VG
          - VI
          - VN
          - VU
          - WF
          - WS
          - YE
          - YT
          - ZA
          - ZM
          - ZW
        state_code:
          type: string
          nullable: true
        postal_code_prefix:
          type: string
          nullable: true
        postal_code_from:
          type: string
          nullable: true
        postal_code_to:
          type: string
          nullable: true
        country_name:
          type: string
          nullable: true
        state_name:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
      required:
      - id
      - member_type
      - country_code
      - state_code
      - postal_code_prefix
      - postal_code_from
      - postal_code_to
      - country_name
      - state_name
      - created_at
      - updated_at
      x-typelizer: true
    DeliveryZone:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
          nullable: true
        members:
          type: array
          items:
            "$ref": "#/components/schemas/DeliveryZoneMember"
        created_at:
          type: string
        updated_at:
          type: string
        delivery_profile_id:
          type: string
        delivery_origin_group_id:
          type: string
          nullable: true
        delivery_method_ids:
          type: array
          items:
            type: string
      required:
      - id
      - name
      - description
      - created_at
      - updated_at
      - delivery_profile_id
      - delivery_origin_group_id
      - delivery_method_ids
      x-typelizer: true
    Diagnostics:
      type: object
      properties:
        spree_version:
          type: string
        sections:
          type: array
          items:
            type: object
        errors:
          type: array
          items:
            type: object
        generated_at:
          type: string
        markdown:
          type: string
        issue_url:
          type: string
        issue_prefilled:
          type: boolean
      required:
      - spree_version
      - sections
      - errors
      - generated_at
      - markdown
      - issue_url
      - issue_prefilled
      x-typelizer: true
    DigitalAsset:
      type: object
      properties:
        id:
          type: string
        variant_id:
          type: string
          nullable: true
        filename:
          type: string
          nullable: true
        content_type:
          type: string
          nullable: true
        authorized_clicks:
          type: number
          nullable: true
        authorized_days:
          type: number
          nullable: true
        byte_size:
          type: number
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        provider_type:
          type: string
          nullable: true
          description: 'Digital asset provider; null is an uploaded file. Built-in:
            file. Extensions may register more.'
        provider_name:
          type: string
          description: 'Digital asset provider name. Built-in: File. Extensions may
            register more.'
        download_url:
          type: string
          nullable: true
        effective_authorized_clicks:
          type: number
        effective_authorized_days:
          type: number
        provider_settings:
          type: object
      required:
      - id
      - variant_id
      - filename
      - content_type
      - authorized_clicks
      - authorized_days
      - byte_size
      - created_at
      - updated_at
      - provider_type
      - provider_name
      - download_url
      - effective_authorized_clicks
      - effective_authorized_days
      - provider_settings
      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
        expires_at:
          type: string
          nullable: true
        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
      - expires_at
      - authorizable
      - expired
      - access_limit_exceeded
      - created_at
      - updated_at
      x-typelizer: true
    Discount:
      type: object
      properties:
        id:
          type: string
        label:
          type: string
        kind:
          type: string
          enum:
          - promotion
          - manual
        code:
          type: string
          nullable: true
        value_type:
          type: string
          nullable: true
        value:
          type: string
          nullable: true
        promotion_id:
          type: string
          nullable: true
        line_item_id:
          type: string
          nullable: true
        fulfillment_id:
          type: string
          nullable: true
        amount:
          type: string
        metadata:
          type: object
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
      required:
      - id
      - label
      - kind
      - code
      - value_type
      - value
      - promotion_id
      - line_item_id
      - fulfillment_id
      - amount
      - metadata
      - created_at
      - updated_at
      x-typelizer: true
    EmailTemplateDraft:
      type: object
      properties:
        id:
          type: string
        subject:
          type: string
          nullable: true
        body:
          type: string
        lock_version:
          type: number
        created_at:
          type: string
        updated_at:
          type: string
        updated_by_id:
          type: string
          nullable: true
        updated_by_type:
          anyOf:
          - type: string
            enum:
            - admin_user
            - api_key
          - type: string
            nullable: true
          description: The values listed are the built-in ones; extensions may add
            more.
        updated_by:
          "$ref": "#/components/schemas/Actor"
      required:
      - id
      - subject
      - body
      - lock_version
      - created_at
      - updated_at
      - updated_by_id
      - updated_by_type
      x-typelizer: true
    EmailTemplatePreview:
      type: object
      properties:
        id:
          type: string
          nullable: true
        subject:
          type: string
        html:
          type: string
        text:
          type: string
        email_key:
          type: string
        variables:
          type: object
      required:
      - id
      - subject
      - html
      - text
      - email_key
      - variables
      x-typelizer: true
    EmailTemplateRevision:
      type: object
      properties:
        id:
          type: string
        subject:
          type: string
          nullable: true
        body:
          type: string
        created_at:
          type: string
        published_by_id:
          type: string
          nullable: true
        published_by_type:
          anyOf:
          - type: string
            enum:
            - admin_user
            - api_key
          - type: string
            nullable: true
          description: The values listed are the built-in ones; extensions may add
            more.
        published_by:
          "$ref": "#/components/schemas/Actor"
      required:
      - id
      - subject
      - body
      - created_at
      - published_by_id
      - published_by_type
      x-typelizer: true
    EmailTemplateSampleRecord:
      type: object
      properties:
        id:
          type: string
        label:
          type: string
        created_at:
          type: string
      required:
      - id
      - label
      - created_at
      x-typelizer: true
    EmailTemplate:
      type: object
      properties:
        id:
          type: string
        key:
          type: string
        subject:
          type: string
          nullable: true
        body:
          type: string
        language:
          type: string
        customized_languages:
          type: array
          items:
            type: string
        kind:
          type: string
          enum:
          - email
          - layout
          - partial
        customized:
          type: boolean
        published_at:
          type: string
          nullable: true
        default_subject:
          type: string
          nullable: true
        default_body:
          type: string
        published_language:
          type: string
          nullable: true
        default_changed:
          type: boolean
        base_subject:
          type: string
          nullable: true
        base_body:
          type: string
          nullable: true
        draft:
          allOf:
          - "$ref": "#/components/schemas/EmailTemplateDraft"
          nullable: true
      required:
      - id
      - key
      - subject
      - body
      - language
      - customized_languages
      - kind
      - customized
      - published_at
      - default_subject
      - default_body
      - published_language
      - default_changed
      - base_subject
      - base_body
      - draft
      x-typelizer: true
    ExchangeLineItem:
      type: object
      properties:
        id:
          type: string
        quantity:
          type: number
        received_quantity:
          type: number
        resellable:
          type: boolean
        original_price:
          type: string
        new_variant_price:
          type: string
        price_difference:
          type: string
        original_tax_total:
          type: string
        new_tax_total:
          type: string
        original_variant_id:
          type: string
          nullable: true
        new_variant_id:
          type: string
          nullable: true
        line_item_id:
          type: string
          nullable: true
        fulfillment_item_id:
          type: string
          nullable: true
        original_variant:
          "$ref": "#/components/schemas/Variant"
        new_variant:
          "$ref": "#/components/schemas/Variant"
        created_at:
          type: string
        updated_at:
          type: string
      required:
      - id
      - quantity
      - received_quantity
      - resellable
      - original_price
      - new_variant_price
      - price_difference
      - original_tax_total
      - new_tax_total
      - original_variant_id
      - new_variant_id
      - line_item_id
      - fulfillment_item_id
      - created_at
      - updated_at
      x-typelizer: true
    Exchange:
      type: object
      properties:
        id:
          type: string
        number:
          type: string
        status:
          anyOf:
          - type: string
            enum:
            - requested
            - approved
            - received
            - fulfilled
            - canceled
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        order_id:
          type: string
          nullable: true
        reason_id:
          type: string
          nullable: true
        price_difference:
          type: string
        approved_at:
          type: string
          nullable: true
        received_at:
          type: string
          nullable: true
        fulfilled_at:
          type: string
          nullable: true
        canceled_at:
          type: string
          nullable: true
        reason:
          "$ref": "#/components/schemas/ReturnReason"
        exchange_line_items:
          type: array
          items:
            "$ref": "#/components/schemas/ExchangeLineItem"
        memo:
          type: string
          nullable: true
        metadata:
          type: object
        created_at:
          type: string
        updated_at:
          type: string
        stock_location_id:
          type: string
          nullable: true
        created_by_id:
          type: string
          nullable: true
        created_by_type:
          anyOf:
          - type: string
            enum:
            - admin_user
            - api_key
          - type: string
            nullable: true
          description: The values listed are the built-in ones; extensions may add
            more.
        created_by:
          "$ref": "#/components/schemas/Actor"
        order:
          "$ref": "#/components/schemas/Order"
        stock_location:
          "$ref": "#/components/schemas/StockLocation"
        refunds:
          type: array
          items:
            "$ref": "#/components/schemas/Refund"
      required:
      - id
      - number
      - status
      - order_id
      - reason_id
      - price_difference
      - approved_at
      - received_at
      - fulfilled_at
      - canceled_at
      - memo
      - metadata
      - created_at
      - updated_at
      - stock_location_id
      - created_by_id
      - created_by_type
      x-typelizer: true
    Export:
      type: object
      properties:
        id:
          type: string
        number:
          type: string
        format:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        type:
          type: string
          nullable: true
        user_id:
          type: string
          nullable: true
        done:
          type: boolean
        store_id:
          type: string
          nullable: true
        seller_id:
          type: string
          nullable: true
        seller_name:
          type: string
          nullable: true
        filename:
          type: string
          nullable: true
        byte_size:
          type: number
          nullable: true
        download_url:
          type: string
          nullable: true
      required:
      - id
      - number
      - format
      - created_at
      - updated_at
      - type
      - user_id
      - done
      - store_id
      - seller_id
      - seller_name
      - filename
      - byte_size
      - download_url
      x-typelizer: true
    Fee:
      type: object
      properties:
        id:
          type: string
        label:
          type: string
        kind:
          anyOf:
          - type: string
            enum:
            - surcharge
            - handling
            - gift_wrap
            - cod
            - payment
            - duty
            - exchange
          - type: string
          description: What sort of charge this is. `duty` is a customs duty on a
            cross-border order and is not taxed; the other kinds are. Extensions may
            register further kinds.
        line_item_id:
          type: string
          nullable: true
        fulfillment_id:
          type: string
          nullable: true
        amount:
          type: string
        metadata:
          type: object
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
      required:
      - id
      - label
      - kind
      - line_item_id
      - fulfillment_id
      - amount
      - metadata
      - created_at
      - updated_at
      x-typelizer: true
    FileUpload:
      type: object
      properties:
        signed_id:
          type: string
        filename:
          type: string
        content_type:
          type: string
        byte_size:
          type: number
        visibility:
          type: string
          enum:
          - public
          - private
        expires_at:
          type: string
        upload:
          allOf:
          - "$ref": "#/components/schemas/FileUploadTarget"
          nullable: true
      required:
      - signed_id
      - filename
      - content_type
      - byte_size
      - visibility
      - expires_at
      - upload
      x-typelizer: true
    FileUploadTarget:
      type: object
      properties:
        method:
          type: string
        url:
          type: string
        headers:
          type: object
      required:
      - method
      - url
      - headers
      x-typelizer: true
    FreightSummaryLine:
      type: object
      properties:
        variant_id:
          type: string
          nullable: true
        sku:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        units:
          type: number
        cartons:
          type: number
          nullable: true
        pallets:
          type: number
          nullable: true
        units_per_carton:
          type: number
          nullable: true
        cartons_per_pallet:
          type: number
          nullable: true
        complete:
          type: boolean
        weight_per_carton:
          type: string
          nullable: true
        volume:
          type: string
        weight:
          type: string
      required:
      - variant_id
      - sku
      - name
      - units
      - cartons
      - pallets
      - units_per_carton
      - cartons_per_pallet
      - complete
      - weight_per_carton
      - volume
      - weight
      x-typelizer: true
    FreightSummary:
      type: object
      properties:
        total_units:
          type: number
        total_cartons:
          type: number
        total_pallets:
          type: number
          nullable: true
        total_volume:
          type: string
        total_weight:
          type: string
        complete:
          type: boolean
        lines:
          type: array
          items:
            "$ref": "#/components/schemas/FreightSummaryLine"
      required:
      - total_units
      - total_cartons
      - total_pallets
      - total_volume
      - total_weight
      - complete
      - lines
      x-typelizer: true
    FulfillmentItem:
      type: object
      properties:
        id:
          type: string
        quantity:
          type: number
        status:
          anyOf:
          - type: string
            enum:
            - on_hand
            - backordered
            - shipped
            - returned
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        variant_id:
          type: string
          nullable: true
        line_item_id:
          type: string
          nullable: true
        name:
          type: string
          nullable: true
        options_text:
          type: string
          nullable: true
      required:
      - id
      - quantity
      - status
      - variant_id
      - line_item_id
      - name
      - options_text
      x-typelizer: true
    Fulfillment:
      type: object
      properties:
        id:
          type: string
        number:
          type: string
        tracking:
          type: string
          nullable: true
        tracking_url:
          type: string
          nullable: true
        pickup_point_data:
          type: object
          nullable: true
        selected_delivery_rate_id:
          type: string
          nullable: true
        unpriced:
          type: boolean
        cost:
          type: string
        total:
          type: string
        discount_total:
          type: string
        additional_tax_total:
          type: string
        included_tax_total:
          type: string
        tax_total:
          type: string
        status:
          anyOf:
          - type: string
            enum:
            - unfulfilled
            - fulfilled
            - delivered
            - canceled
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        fulfillment_type:
          type: string
          enum:
          - shipping
          - digital
          - pickup
          - pickup_point
        fulfilled_at:
          type: string
          nullable: true
        delivered_at:
          type: string
          nullable: true
        items:
          type: array
          items:
            "$ref": "#/components/schemas/FulfillmentManifestItem"
        deliveries:
          type: array
          items:
            "$ref": "#/components/schemas/Delivery"
        delivery_method:
          "$ref": "#/components/schemas/DeliveryMethod"
        stock_location:
          "$ref": "#/components/schemas/StockLocation"
        delivery_rates:
          type: array
          items:
            "$ref": "#/components/schemas/DeliveryRate"
        tax_lines:
          type: array
          items:
            "$ref": "#/components/schemas/TaxLine"
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        external_references:
          type: object
        metadata:
          type: object
        created_at:
          type: string
        updated_at:
          type: string
        adjustment_total:
          type: string
        pre_tax_amount:
          type: string
        order_id:
          type: string
          nullable: true
        stock_location_id:
          type: string
          nullable: true
        documents:
          type: array
          items:
            type: object
            properties:
              kind:
                type: string
              url:
                type: string
            required:
            - kind
            - url
        labels:
          type: array
          items:
            "$ref": "#/components/schemas/ShippingLabel"
        provider_generates_labels:
          type: boolean
        fulfillment_items:
          type: array
          items:
            "$ref": "#/components/schemas/FulfillmentItem"
        order:
          "$ref": "#/components/schemas/Order"
      required:
      - id
      - number
      - tracking
      - tracking_url
      - pickup_point_data
      - selected_delivery_rate_id
      - unpriced
      - cost
      - total
      - discount_total
      - additional_tax_total
      - included_tax_total
      - tax_total
      - status
      - fulfillment_type
      - fulfilled_at
      - delivered_at
      - items
      - deliveries
      - external_references
      - metadata
      - created_at
      - updated_at
      - adjustment_total
      - pre_tax_amount
      - order_id
      - stock_location_id
      - documents
      - labels
      - provider_generates_labels
      x-typelizer: true
    GiftCardBatch:
      type: object
      properties:
        id:
          type: string
        codes_count:
          type: number
        currency:
          type: string
          nullable: true
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        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:
          anyOf:
          - type: string
            enum:
            - active
            - partially_redeemed
            - redeemed
            - canceled
            - expired
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        amount:
          type: string
        amount_used:
          type: string
        amount_authorized:
          type: string
        amount_remaining:
          type: string
        expires_at:
          type: string
          nullable: true
        redeemed_at:
          type: string
          nullable: true
        expired:
          type: boolean
        active:
          type: boolean
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        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
      - expires_at
      - redeemed_at
      - expired
      - active
      - created_at
      - updated_at
      - customer_id
      - created_by_id
      x-typelizer: true
    ImportMapping:
      type: object
      properties:
        id:
          type: string
        schema_field:
          type: string
        file_column:
          type: string
          nullable: true
        required:
          type: boolean
      required:
      - id
      - schema_field
      - file_column
      - required
      x-typelizer: true
    ImportRow:
      type: object
      properties:
        id:
          type: string
        row_number:
          type: number
        status:
          anyOf:
          - type: string
            enum:
            - pending
            - processing
            - completed
            - failed
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        validation_errors:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        import_id:
          type: string
          nullable: true
        item_type:
          type: string
          nullable: true
        item_id:
          type: string
          nullable: true
        data:
          type: object
      required:
      - id
      - row_number
      - status
      - validation_errors
      - created_at
      - updated_at
      - import_id
      - item_type
      - item_id
      - data
      x-typelizer: true
    Import:
      type: object
      properties:
        id:
          type: string
        number:
          type: string
        rows_count:
          type: number
        created_at:
          type: string
        updated_at:
          type: string
        type:
          type: string
          nullable: true
          description: 'Import type. Built-in: products, product_translations, customers,
            price_list_prices. Extensions may register more.'
        status:
          anyOf:
          - type: string
            enum:
            - pending
            - mapping
            - completed_mapping
            - processing
            - completed
            - failed
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        store_id:
          type: string
          nullable: true
        seller_id:
          type: string
          nullable: true
        user_id:
          type: string
          nullable: true
        processing_errors:
          type: string
          nullable: true
        delimiter:
          type: string
        price_list_id:
          type: string
          nullable: true
        seller_name:
          type: string
          nullable: true
        original_filename:
          type: string
          nullable: true
        original_byte_size:
          type: number
          nullable: true
        original_file_url:
          type: string
          nullable: true
        completed_rows_count:
          type: number
        failed_rows_count:
          type: number
        schema_fields:
          type: array
          items:
            "$ref": "#/components/schemas/ImportSchemaField"
        csv_headers:
          type: array
          items:
            type: string
        sample_row:
          type: object
        mappings:
          type: array
          items:
            "$ref": "#/components/schemas/ImportMapping"
      required:
      - id
      - number
      - rows_count
      - created_at
      - updated_at
      - type
      - status
      - store_id
      - seller_id
      - user_id
      - processing_errors
      - delimiter
      - price_list_id
      - seller_name
      - original_filename
      - original_byte_size
      - original_file_url
      - completed_rows_count
      - failed_rows_count
      - schema_fields
      - csv_headers
      - sample_row
      - mappings
      x-typelizer: true
    Integration:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        active:
          type: boolean
        created_at:
          type: string
        updated_at:
          type: string
        type:
          type: string
          description: Integration type, registered by the provider gem that owns
            it (for example the EasyPost provider). Core ships none.
        group:
          type: string
          nullable: true
        preferences:
          "$ref": "#/components/schemas/IntegrationPreferences"
      required:
      - id
      - name
      - active
      - created_at
      - updated_at
      - type
      - group
      - preferences
      x-typelizer: true
    InvitationAcceptanceLink:
      type: object
      properties:
        id:
          type: string
        acceptance_url:
          type: string
      required:
      - id
      - acceptance_url
      x-typelizer: true
    Invitation:
      type: object
      properties:
        id:
          type: string
        email:
          type: string
        status:
          anyOf:
          - type: string
            enum:
            - pending
            - accepted
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        created_at:
          type: string
        updated_at:
          type: string
        expires_at:
          type: string
        role_id:
          type: string
        role_name:
          type: string
        inviter_email:
          type: string
        invitee_exists:
          type: boolean
        store:
          type: object
          properties:
            id:
              type: string
            name:
              type: string
          required:
          - id
          - name
      required:
      - id
      - email
      - status
      - created_at
      - updated_at
      - expires_at
      - role_id
      - role_name
      - inviter_email
      - invitee_exists
      - store
      x-typelizer: true
    LineItem:
      type: object
      properties:
        id:
          type: string
        variant_id:
          type: string
        seller_id:
          type: string
          nullable: true
        preorder:
          type: boolean
        preorder_ships_at:
          type: string
          nullable: true
        quantity:
          type: number
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        name:
          type: string
        slug:
          type: string
        options_text:
          type: string
        price:
          type: string
          description: The price of one unit.
        total:
          type: string
          description: 'What this line costs: price times quantity, with its discounts,
            fees and added tax.'
        adjustment_total:
          type: string
          description: This line's discounts, fees and added tax together.
        additional_tax_total:
          type: string
          description: Tax added on top of the price.
        included_tax_total:
          type: string
          description: Tax already included in the price.
        discount_total:
          type: string
          description: What promotions take off this line, as a negative amount.
        pre_tax_amount:
          type: string
          description: This line after discounts, without tax.
        discounted_amount:
          type: string
          description: Price times quantity, after discounts.
        compare_at_amount:
          type: string
          nullable: true
          description: The compare-at price times quantity, or null when the variant
            has none.
        thumbnail_url:
          type: string
          nullable: true
        seller:
          "$ref": "#/components/schemas/Seller"
        option_values:
          type: array
          items:
            "$ref": "#/components/schemas/OptionValue"
        digital_links:
          type: array
          items:
            "$ref": "#/components/schemas/DigitalLink"
        tax_lines:
          type: array
          items:
            "$ref": "#/components/schemas/TaxLine"
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        external_references:
          type: object
        metadata:
          type: object
        price_source:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        catalog_price:
          type: string
          nullable: true
        price_list_id:
          type: string
          nullable: true
        price_list_name:
          type: string
          nullable: true
        catalog_id:
          type: string
          nullable: true
        catalog_name:
          type: string
          nullable: true
        cost_price:
          type: string
          nullable: true
        tax_category_id:
          type: string
          nullable: true
        product_id:
          type: string
          nullable: true
        variant:
          "$ref": "#/components/schemas/Variant"
        tax_category:
          "$ref": "#/components/schemas/TaxCategory"
      required:
      - id
      - variant_id
      - seller_id
      - preorder
      - preorder_ships_at
      - quantity
      - currency
      - name
      - slug
      - options_text
      - price
      - total
      - adjustment_total
      - additional_tax_total
      - included_tax_total
      - discount_total
      - pre_tax_amount
      - discounted_amount
      - compare_at_amount
      - thumbnail_url
      - option_values
      - digital_links
      - external_references
      - metadata
      - price_source
      - created_at
      - updated_at
      - catalog_price
      - price_list_id
      - price_list_name
      - catalog_id
      - catalog_name
      - cost_price
      - tax_category_id
      - product_id
      x-typelizer: true
    Locale:
      type: object
      properties:
        code:
          type: string
          enum:
          - aa
          - ab
          - ae
          - af
          - ak
          - am
          - an
          - ar
          - as
          - av
          - ay
          - az
          - ba
          - be
          - bg
          - bh
          - bi
          - bm
          - bn
          - bo
          - br
          - bs
          - ca
          - ce
          - ch
          - co
          - cr
          - cs
          - cu
          - cv
          - cy
          - da
          - de
          - de-AT
          - de-CH
          - dv
          - dz
          - ee
          - el
          - en
          - en-AU
          - en-CA
          - en-GB
          - en-IN
          - en-NZ
          - en-US
          - eo
          - es
          - es-419
          - es-CL
          - es-EC
          - es-MX
          - et
          - eu
          - fa
          - ff
          - fi
          - fj
          - fo
          - fr
          - fr-CA
          - fy
          - ga
          - gd
          - gl
          - gn
          - gu
          - gv
          - ha
          - he
          - hi
          - ho
          - hr
          - ht
          - hu
          - hy
          - hz
          - ia
          - id
          - ie
          - ig
          - ii
          - ik
          - io
          - is
          - it
          - iu
          - ja
          - jv
          - ka
          - kg
          - ki
          - kj
          - kk
          - kl
          - km
          - kn
          - ko
          - kr
          - ks
          - ku
          - kv
          - kw
          - ky
          - la
          - lb
          - lg
          - li
          - ln
          - lo
          - lt
          - lu
          - lv
          - mg
          - mh
          - mi
          - mk
          - ml
          - mn
          - mr
          - ms
          - mt
          - my
          - na
          - nb
          - nd
          - ne
          - ng
          - nl
          - nn
          - 'no'
          - nr
          - nv
          - ny
          - oc
          - oj
          - om
          - or
          - os
          - pa
          - pi
          - pl
          - ps
          - pt
          - pt-BR
          - pt-PT
          - qu
          - rm
          - rn
          - ro
          - ru
          - rw
          - sa
          - sc
          - sd
          - se
          - sg
          - si
          - sk
          - sl
          - sl-SI
          - sm
          - sn
          - so
          - sq
          - sr
          - ss
          - st
          - su
          - sv
          - sw
          - ta
          - te
          - tg
          - th
          - ti
          - tk
          - tl
          - tn
          - to
          - tr
          - ts
          - tt
          - tw
          - ty
          - ug
          - uk
          - ur
          - uz
          - ve
          - vi
          - vo
          - wa
          - wo
          - xh
          - yi
          - yo
          - za
          - zh-CN
          - zh-HK
          - zh-TW
          - zu
        default:
          type: boolean
        rtl:
          type: boolean
      required:
      - code
      - default
      - rtl
      x-typelizer: true
    MaintenanceTaskRun:
      type: object
      properties:
        id:
          type: string
        status:
          anyOf:
          - type: string
            enum:
            - enqueued
            - running
            - interrupted
            - cancelling
            - cancelled
            - succeeded
            - errored
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        dry_run:
          type: boolean
        initiated_via:
          type: string
        tick_count:
          type: number
        tick_total:
          type: number
          nullable: true
        error_class:
          type: string
          nullable: true
        error_message:
          type: string
          nullable: true
        started_at:
          type: string
          nullable: true
        ended_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        task_name:
          type: string
        duration:
          type: number
          nullable: true
        tallies:
          type: object
        arguments:
          type: object
        error_backtrace:
          type: string
          nullable: true
        active:
          type: boolean
        admin_user_id:
          type: string
          nullable: true
        admin_user:
          "$ref": "#/components/schemas/AdminUser"
      required:
      - id
      - status
      - dry_run
      - initiated_via
      - tick_count
      - tick_total
      - error_class
      - error_message
      - started_at
      - ended_at
      - created_at
      - updated_at
      - task_name
      - duration
      - tallies
      - arguments
      - error_backtrace
      - active
      - admin_user_id
      x-typelizer: true
    Market:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        default_locale:
          type: string
          enum:
          - aa
          - ab
          - ae
          - af
          - ak
          - am
          - an
          - ar
          - as
          - av
          - ay
          - az
          - ba
          - be
          - bg
          - bh
          - bi
          - bm
          - bn
          - bo
          - br
          - bs
          - ca
          - ce
          - ch
          - co
          - cr
          - cs
          - cu
          - cv
          - cy
          - da
          - de
          - de-AT
          - de-CH
          - dv
          - dz
          - ee
          - el
          - en
          - en-AU
          - en-CA
          - en-GB
          - en-IN
          - en-NZ
          - en-US
          - eo
          - es
          - es-419
          - es-CL
          - es-EC
          - es-MX
          - et
          - eu
          - fa
          - ff
          - fi
          - fj
          - fo
          - fr
          - fr-CA
          - fy
          - ga
          - gd
          - gl
          - gn
          - gu
          - gv
          - ha
          - he
          - hi
          - ho
          - hr
          - ht
          - hu
          - hy
          - hz
          - ia
          - id
          - ie
          - ig
          - ii
          - ik
          - io
          - is
          - it
          - iu
          - ja
          - jv
          - ka
          - kg
          - ki
          - kj
          - kk
          - kl
          - km
          - kn
          - ko
          - kr
          - ks
          - ku
          - kv
          - kw
          - ky
          - la
          - lb
          - lg
          - li
          - ln
          - lo
          - lt
          - lu
          - lv
          - mg
          - mh
          - mi
          - mk
          - ml
          - mn
          - mr
          - ms
          - mt
          - my
          - na
          - nb
          - nd
          - ne
          - ng
          - nl
          - nn
          - 'no'
          - nr
          - nv
          - ny
          - oc
          - oj
          - om
          - or
          - os
          - pa
          - pi
          - pl
          - ps
          - pt
          - pt-BR
          - pt-PT
          - qu
          - rm
          - rn
          - ro
          - ru
          - rw
          - sa
          - sc
          - sd
          - se
          - sg
          - si
          - sk
          - sl
          - sl-SI
          - sm
          - sn
          - so
          - sq
          - sr
          - ss
          - st
          - su
          - sv
          - sw
          - ta
          - te
          - tg
          - th
          - ti
          - tk
          - tl
          - tn
          - to
          - tr
          - ts
          - tt
          - tw
          - ty
          - ug
          - uk
          - ur
          - uz
          - ve
          - vi
          - vo
          - wa
          - wo
          - xh
          - yi
          - yo
          - za
          - zh-CN
          - zh-HK
          - zh-TW
          - zu
        tax_inclusive:
          type: boolean
        default:
          type: boolean
        country_codes:
          type: array
          items:
            type: string
            enum:
            - AD
            - AE
            - AF
            - AG
            - AI
            - AL
            - AM
            - AO
            - AR
            - AS
            - AT
            - AU
            - AW
            - AZ
            - BA
            - BB
            - BD
            - BE
            - BF
            - BG
            - BH
            - BI
            - BJ
            - BL
            - BM
            - BN
            - BO
            - BQ
            - BR
            - BS
            - BT
            - BW
            - BY
            - BZ
            - CA
            - CC
            - CD
            - CF
            - CG
            - CH
            - CI
            - CK
            - CL
            - CM
            - CN
            - CO
            - CR
            - CU
            - CV
            - CW
            - CX
            - CY
            - CZ
            - DE
            - DJ
            - DK
            - DM
            - DO
            - DZ
            - EC
            - EE
            - EG
            - ER
            - ES
            - ET
            - FI
            - FJ
            - FK
            - FM
            - FO
            - FR
            - GA
            - GB
            - GD
            - GE
            - GF
            - GG
            - GH
            - GI
            - GL
            - GM
            - GN
            - GP
            - GQ
            - GR
            - GT
            - GU
            - GW
            - GY
            - HK
            - HN
            - HR
            - HT
            - HU
            - ID
            - IE
            - IL
            - IM
            - IN
            - IQ
            - IR
            - IS
            - IT
            - JE
            - JM
            - JO
            - JP
            - KE
            - KG
            - KH
            - KI
            - KM
            - KN
            - KP
            - KR
            - KW
            - KY
            - KZ
            - LA
            - LB
            - LC
            - LI
            - LK
            - LR
            - LS
            - LT
            - LU
            - LV
            - LY
            - MA
            - MC
            - MD
            - ME
            - MF
            - MG
            - MH
            - MK
            - ML
            - MM
            - MN
            - MO
            - MP
            - MQ
            - MR
            - MS
            - MT
            - MU
            - MV
            - MW
            - MX
            - MY
            - MZ
            - NA
            - NC
            - NE
            - NF
            - NG
            - NI
            - NL
            - 'NO'
            - NP
            - NR
            - NU
            - NZ
            - OM
            - PA
            - PE
            - PF
            - PG
            - PH
            - PK
            - PL
            - PM
            - PN
            - PR
            - PS
            - PT
            - PW
            - PY
            - QA
            - RE
            - RO
            - RS
            - RU
            - RW
            - SA
            - SB
            - SC
            - SD
            - SE
            - SG
            - SH
            - SI
            - SJ
            - SK
            - SL
            - SM
            - SN
            - SO
            - SR
            - SS
            - ST
            - SV
            - SX
            - SY
            - SZ
            - TC
            - TD
            - TG
            - TH
            - TJ
            - TK
            - TL
            - TM
            - TN
            - TO
            - TR
            - TT
            - TV
            - TW
            - TZ
            - UA
            - UG
            - US
            - UY
            - UZ
            - VA
            - VC
            - VE
            - VG
            - VI
            - VN
            - VU
            - WF
            - WS
            - YE
            - YT
            - ZA
            - ZM
            - ZW
        supported_locales:
          type: array
          items:
            type: string
            enum:
            - aa
            - ab
            - ae
            - af
            - ak
            - am
            - an
            - ar
            - as
            - av
            - ay
            - az
            - ba
            - be
            - bg
            - bh
            - bi
            - bm
            - bn
            - bo
            - br
            - bs
            - ca
            - ce
            - ch
            - co
            - cr
            - cs
            - cu
            - cv
            - cy
            - da
            - de
            - de-AT
            - de-CH
            - dv
            - dz
            - ee
            - el
            - en
            - en-AU
            - en-CA
            - en-GB
            - en-IN
            - en-NZ
            - en-US
            - eo
            - es
            - es-419
            - es-CL
            - es-EC
            - es-MX
            - et
            - eu
            - fa
            - ff
            - fi
            - fj
            - fo
            - fr
            - fr-CA
            - fy
            - ga
            - gd
            - gl
            - gn
            - gu
            - gv
            - ha
            - he
            - hi
            - ho
            - hr
            - ht
            - hu
            - hy
            - hz
            - ia
            - id
            - ie
            - ig
            - ii
            - ik
            - io
            - is
            - it
            - iu
            - ja
            - jv
            - ka
            - kg
            - ki
            - kj
            - kk
            - kl
            - km
            - kn
            - ko
            - kr
            - ks
            - ku
            - kv
            - kw
            - ky
            - la
            - lb
            - lg
            - li
            - ln
            - lo
            - lt
            - lu
            - lv
            - mg
            - mh
            - mi
            - mk
            - ml
            - mn
            - mr
            - ms
            - mt
            - my
            - na
            - nb
            - nd
            - ne
            - ng
            - nl
            - nn
            - 'no'
            - nr
            - nv
            - ny
            - oc
            - oj
            - om
            - or
            - os
            - pa
            - pi
            - pl
            - ps
            - pt
            - pt-BR
            - pt-PT
            - qu
            - rm
            - rn
            - ro
            - ru
            - rw
            - sa
            - sc
            - sd
            - se
            - sg
            - si
            - sk
            - sl
            - sl-SI
            - sm
            - sn
            - so
            - sq
            - sr
            - ss
            - st
            - su
            - sv
            - sw
            - ta
            - te
            - tg
            - th
            - ti
            - tk
            - tl
            - tn
            - to
            - tr
            - ts
            - tt
            - tw
            - ty
            - ug
            - uk
            - ur
            - uz
            - ve
            - vi
            - vo
            - wa
            - wo
            - xh
            - yi
            - yo
            - za
            - zh-CN
            - zh-HK
            - zh-TW
            - zu
        countries:
          type: array
          items:
            "$ref": "#/components/schemas/Country"
        created_at:
          type: string
        updated_at:
          type: string
        tax_provider:
          type: string
          nullable: true
          description: 'Tax provider; null uses the store default. Built-in: internal.
            Provider gems register more.'
      required:
      - id
      - name
      - currency
      - default_locale
      - tax_inclusive
      - default
      - country_codes
      - supported_locales
      - created_at
      - updated_at
      - tax_provider
      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
          enum:
          - image
          - video
          - external_video
        external_video_url:
          type: string
          nullable: true
        focal_point_x:
          type: number
          nullable: true
        focal_point_y:
          type: number
          nullable: true
        video_provider:
          type: string
          nullable: true
        video_embed_url:
          type: string
          nullable: true
        video_url:
          type: string
          nullable: true
        poster_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
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        external_references:
          type: object
        created_at:
          type: string
        updated_at:
          type: string
        attached:
          type: boolean
        filename:
          type: string
          nullable: true
        content_type:
          type: string
          nullable: true
        byte_size:
          type: number
          nullable: true
        embed_url:
          type: string
          nullable: true
        signed_id:
          type: string
          nullable: true
        viewable_id:
          type: string
          nullable: true
        download_url:
          type: string
          nullable: true
        metadata:
          type: object
        viewable_type:
          type: string
          nullable: true
      required:
      - id
      - product_id
      - variant_ids
      - position
      - alt
      - media_type
      - external_video_url
      - focal_point_x
      - focal_point_y
      - video_provider
      - video_embed_url
      - video_url
      - poster_url
      - original_url
      - mini_url
      - small_url
      - medium_url
      - large_url
      - xlarge_url
      - og_image_url
      - external_references
      - created_at
      - updated_at
      - attached
      - filename
      - content_type
      - byte_size
      - embed_url
      - signed_id
      - viewable_id
      - download_url
      - metadata
      - viewable_type
      x-typelizer: true
    MembershipProduct:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        thumbnail_url:
          type: string
          nullable: true
      required:
      - id
      - name
      - thumbnail_url
      x-typelizer: true
    NewsletterSubscriber:
      type: object
      properties:
        id:
          type: string
        email:
          type: string
        created_at:
          type: string
        updated_at:
          type: string
        verified:
          type: boolean
        verified_at:
          type: string
          nullable: true
        customer_id:
          type: string
          nullable: true
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
      required:
      - id
      - email
      - created_at
      - updated_at
      - verified
      - verified_at
      - customer_id
      x-typelizer: true
    OauthAccessToken:
      type: object
      properties:
        id:
          type: string
        created_at:
          type: string
        owner_id:
          type: string
          nullable: true
        owner_type:
          type: string
          nullable: true
        owner:
          "$ref": "#/components/schemas/AdminUser"
        scopes:
          type: array
          items:
            type: string
        expired:
          type: boolean
      required:
      - id
      - created_at
      - owner_id
      - owner_type
      - scopes
      - expired
      x-typelizer: true
    OauthApplication:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        redirect_uri:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        client_id:
          type: string
        connected:
          type: boolean
        scopes:
          type: array
          items:
            type: string
        last_authorized_at:
          type: string
          nullable: true
        authorized_at:
          type: string
          nullable: true
        authorized_by:
          type: string
          nullable: true
      required:
      - id
      - name
      - redirect_uri
      - created_at
      - updated_at
      - client_id
      - connected
      - scopes
      - last_authorized_at
      - authorized_at
      - authorized_by
      x-typelizer: true
    OauthConsentRequest:
      type: object
      properties:
        client_name:
          type: string
        scopes:
          type: array
          items:
            type: string
        grantable_scopes:
          type: array
          items:
            type: string
        resource:
          type: string
          nullable: true
        redirect_uri:
          type: string
      required:
      - client_name
      - scopes
      - grantable_scopes
      - resource
      - redirect_uri
      x-typelizer: true
    OauthProtectedResource:
      type: object
      properties:
        resource:
          type: string
        authorization_servers:
          type: array
          items:
            type: string
        scopes_supported:
          type: array
          items:
            type: string
        bearer_methods_supported:
          type: array
          items:
            type: string
        resource_documentation:
          type: string
      required:
      - resource
      - authorization_servers
      - scopes_supported
      - bearer_methods_supported
      - resource_documentation
      x-typelizer: true
    OauthRedirect:
      type: object
      properties:
        redirect_uri:
          type: string
      required:
      - redirect_uri
      x-typelizer: true
    OptionType:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        label:
          type: string
        position:
          type: number
        kind:
          type: string
          enum:
          - dropdown
          - color_swatch
          - buttons
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        translations:
          type: object
        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
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        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
    OrderCancellationReason:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        active:
          type: boolean
        created_at:
          type: string
        updated_at:
          type: string
        can_be_deleted:
          type: boolean
      required:
      - id
      - name
      - active
      - created_at
      - updated_at
      - can_be_deleted
      x-typelizer: true
    OrderGroup:
      type: object
      properties:
        id:
          type: string
        number:
          type: string
        email:
          type: string
          nullable: true
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        item_total:
          type: string
          nullable: true
          description: 'The line items: each price times its quantity, before discounts,
            fees and delivery.'
        discount_total:
          type: string
          nullable: true
          description: What promotions take off, as a negative amount. Manual discounts
            are not included.
        tax_total:
          type: string
          nullable: true
          description: All tax, both included in prices and added on top.
        included_tax_total:
          type: string
          nullable: true
          description: Tax already included in the prices, as in a store whose prices
            are tax-inclusive.
        additional_tax_total:
          type: string
          nullable: true
          description: Tax added on top of the prices.
        delivery_total:
          type: string
          nullable: true
          description: What delivery costs, before delivery discounts.
        fee_total:
          type: string
          nullable: true
          description: Every fee charged, such as handling or a customs duty.
        gift_card_total:
          type: string
          nullable: true
          description: What a gift card pays.
        store_credit_total:
          type: string
          nullable: true
          description: What store credit pays, apart from gift cards.
        total:
          type: string
          nullable: true
          description: 'What the customer pays in all: items, delivery, fees and added
            tax, less discounts.'
        amount_due:
          type: string
          nullable: true
          description: What is left to pay after payments and store credit.
        covered_by_store_credit:
          type: boolean
        payments:
          type: array
          items:
            "$ref": "#/components/schemas/Payment"
        fulfillment_status:
          type: string
          nullable: true
          enum:
          - backorder
          - canceled
          - partial
          - unfulfilled
          - fulfilled
          - delivered
          - pending
          - ready
          - shipped
        payment_status:
          type: string
          nullable: true
          enum:
          - none
          - authorized
          - partially_paid
          - paid
          - partially_refunded
          - refunded
          - overcharged
          - voided
        completed_at:
          type: string
          nullable: true
        billing_address:
          allOf:
          - "$ref": "#/components/schemas/Address"
          nullable: true
        shipping_address:
          allOf:
          - "$ref": "#/components/schemas/Address"
          nullable: true
        orders:
          type: array
          items:
            "$ref": "#/components/schemas/Order"
        customer_id:
          type: string
          nullable: true
        cart_id:
          type: string
          nullable: true
        seller_count:
          type: number
        includes_first_party:
          type: boolean
        confirmation_delivered:
          type: boolean
        store_owner_notification_delivered:
          type: boolean
        created_at:
          type: string
        updated_at:
          type: string
      required:
      - id
      - number
      - email
      - currency
      - item_total
      - discount_total
      - tax_total
      - included_tax_total
      - additional_tax_total
      - delivery_total
      - fee_total
      - gift_card_total
      - store_credit_total
      - total
      - amount_due
      - covered_by_store_credit
      - payments
      - fulfillment_status
      - payment_status
      - completed_at
      - billing_address
      - shipping_address
      - orders
      - customer_id
      - cart_id
      - seller_count
      - includes_first_party
      - confirmation_delivered
      - store_owner_notification_delivered
      - created_at
      - updated_at
      x-typelizer: true
    OrderRoutingRule:
      type: object
      properties:
        id:
          type: string
        position:
          type: number
        active:
          type: boolean
        created_at:
          type: string
        updated_at:
          type: string
        type:
          type: string
          description: 'Rule type. Built-in: preferred_location, default_location,
            minimize_splits. Extensions may register more.'
        channel_id:
          type: string
        preferences:
          "$ref": "#/components/schemas/OrderRoutingRulePreferences"
      required:
      - id
      - position
      - active
      - created_at
      - updated_at
      - type
      - channel_id
      - preferences
      x-typelizer: true
    Order:
      type: object
      properties:
        id:
          type: string
        market_id:
          type: string
          nullable: true
        withdrawal_period_ends_at:
          type: string
          nullable: true
        within_withdrawal_period:
          type: boolean
        shipping_eq_billing_address:
          type: boolean
        cart_id:
          type: string
          nullable: true
        channel_id:
          type: string
          nullable: true
        company_id:
          type: string
          nullable: true
        company_name:
          type: string
          nullable: true
        po_document_filename:
          type: string
          nullable: true
        po_document_byte_size:
          type: number
          nullable: true
        number:
          type: string
        email:
          type: string
        customer_note:
          type: string
          nullable: true
        po_number:
          type: string
          nullable: true
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        locale:
          type: string
          nullable: true
          enum:
          - aa
          - ab
          - ae
          - af
          - ak
          - am
          - an
          - ar
          - as
          - av
          - ay
          - az
          - ba
          - be
          - bg
          - bh
          - bi
          - bm
          - bn
          - bo
          - br
          - bs
          - ca
          - ce
          - ch
          - co
          - cr
          - cs
          - cu
          - cv
          - cy
          - da
          - de
          - de-AT
          - de-CH
          - dv
          - dz
          - ee
          - el
          - en
          - en-AU
          - en-CA
          - en-GB
          - en-IN
          - en-NZ
          - en-US
          - eo
          - es
          - es-419
          - es-CL
          - es-EC
          - es-MX
          - et
          - eu
          - fa
          - ff
          - fi
          - fj
          - fo
          - fr
          - fr-CA
          - fy
          - ga
          - gd
          - gl
          - gn
          - gu
          - gv
          - ha
          - he
          - hi
          - ho
          - hr
          - ht
          - hu
          - hy
          - hz
          - ia
          - id
          - ie
          - ig
          - ii
          - ik
          - io
          - is
          - it
          - iu
          - ja
          - jv
          - ka
          - kg
          - ki
          - kj
          - kk
          - kl
          - km
          - kn
          - ko
          - kr
          - ks
          - ku
          - kv
          - kw
          - ky
          - la
          - lb
          - lg
          - li
          - ln
          - lo
          - lt
          - lu
          - lv
          - mg
          - mh
          - mi
          - mk
          - ml
          - mn
          - mr
          - ms
          - mt
          - my
          - na
          - nb
          - nd
          - ne
          - ng
          - nl
          - nn
          - 'no'
          - nr
          - nv
          - ny
          - oc
          - oj
          - om
          - or
          - os
          - pa
          - pi
          - pl
          - ps
          - pt
          - pt-BR
          - pt-PT
          - qu
          - rm
          - rn
          - ro
          - ru
          - rw
          - sa
          - sc
          - sd
          - se
          - sg
          - si
          - sk
          - sl
          - sl-SI
          - sm
          - sn
          - so
          - sq
          - sr
          - ss
          - st
          - su
          - sv
          - sw
          - ta
          - te
          - tg
          - th
          - ti
          - tk
          - tl
          - tn
          - to
          - tr
          - ts
          - tt
          - tw
          - ty
          - ug
          - uk
          - ur
          - uz
          - ve
          - vi
          - vo
          - wa
          - wo
          - xh
          - yi
          - yo
          - za
          - zh-CN
          - zh-HK
          - zh-TW
          - zu
        total_quantity:
          type: number
        coupon_code:
          type: string
          nullable: true
        fulfillment_status:
          type: string
          nullable: true
          enum:
          - backorder
          - canceled
          - partial
          - unfulfilled
          - fulfilled
          - delivered
          - pending
          - ready
          - shipped
        payment_status:
          type: string
          nullable: true
          enum:
          - none
          - authorized
          - partially_paid
          - paid
          - partially_refunded
          - refunded
          - overcharged
          - voided
        completed_at:
          type: string
          nullable: true
        item_total:
          type: string
          description: 'The line items: each price times its quantity, before discounts,
            fees and delivery.'
        discount_total:
          type: string
          description: What promotions take off, as a negative amount. Manual discounts
            are not included.
        tax_total:
          type: string
          description: All tax, both included in prices and added on top.
        included_tax_total:
          type: string
          description: Tax already included in the prices, as in a store whose prices
            are tax-inclusive.
        additional_tax_total:
          type: string
          description: Tax added on top of the prices.
        delivery_total:
          type: string
          description: What delivery costs, before delivery discounts.
        fee_total:
          type: string
          description: Every fee charged, such as handling or a customs duty.
        gift_card_total:
          type: string
          description: What a gift card pays.
        store_credit_total:
          type: string
          description: What store credit pays, apart from gift cards.
        total:
          type: string
          description: 'What the customer pays in all: items, delivery, fees and added
            tax, less discounts.'
        amount_due:
          type: string
          description: What is left to pay after payments and store credit.
        covered_by_store_credit:
          type: boolean
        payments:
          type: array
          items:
            "$ref": "#/components/schemas/Payment"
        adjustment_total:
          type: string
          description: Every discount, fee and added tax together, as one amount.
        items:
          type: array
          items:
            "$ref": "#/components/schemas/LineItem"
        fulfillments:
          type: array
          items:
            "$ref": "#/components/schemas/Fulfillment"
        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
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        external_references:
          type: object
        status:
          type: string
          enum:
          - draft
          - placed
          - canceled
        last_ip_address:
          type: string
          nullable: true
        considered_risky:
          type: boolean
        confirmation_delivered:
          type: boolean
        store_owner_notification_delivered:
          type: boolean
          nullable: true
        metadata:
          type: object
        cancel_note:
          type: string
          nullable: true
        canceled_at:
          type: string
          nullable: true
        approved_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        payment_total:
          type: string
        commission_amount_total:
          type: string
        commission_tax_total:
          type: string
        commission_total:
          type: string
        preferred_stock_location_id:
          type: string
          nullable: true
        po_document_url:
          type: string
          nullable: true
        seller_id:
          type: string
          nullable: true
        seller:
          "$ref": "#/components/schemas/Seller"
        order_group_id:
          type: string
          nullable: true
        tags:
          type: array
          items:
            type: string
        internal_note:
          type: string
          nullable: true
        internal_note_html:
          type: string
          nullable: true
        approver_id:
          type: string
          nullable: true
        approver_type:
          anyOf:
          - type: string
            enum:
            - admin_user
            - api_key
          - type: string
            nullable: true
          description: The values listed are the built-in ones; extensions may add
            more.
        approver:
          "$ref": "#/components/schemas/Actor"
        canceler_id:
          type: string
          nullable: true
        canceler_type:
          anyOf:
          - type: string
            enum:
            - admin_user
            - api_key
          - type: string
            nullable: true
          description: The values listed are the built-in ones; extensions may add
            more.
        canceler:
          "$ref": "#/components/schemas/Actor"
        created_by_id:
          type: string
          nullable: true
        created_by_type:
          anyOf:
          - type: string
            enum:
            - admin_user
            - api_key
          - type: string
            nullable: true
          description: The values listed are the built-in ones; extensions may add
            more.
        created_by:
          "$ref": "#/components/schemas/Actor"
        cancel_reason_id:
          type: string
          nullable: true
        cancel_reason_name:
          type: string
          nullable: true
        customer_id:
          type: string
          nullable: true
        applied_promotions:
          type: array
          items:
            "$ref": "#/components/schemas/AppliedPromotion"
        payment_splits:
          type: array
          items:
            "$ref": "#/components/schemas/PaymentSplit"
        cart:
          "$ref": "#/components/schemas/Cart"
        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"
        cancel_reason:
          "$ref": "#/components/schemas/OrderCancellationReason"
        returns:
          type: array
          items:
            "$ref": "#/components/schemas/Return"
        exchanges:
          type: array
          items:
            "$ref": "#/components/schemas/Exchange"
        claims:
          type: array
          items:
            "$ref": "#/components/schemas/Claim"
        freight_summary:
          allOf:
          - "$ref": "#/components/schemas/FreightSummary"
          nullable: true
      required:
      - id
      - market_id
      - withdrawal_period_ends_at
      - within_withdrawal_period
      - shipping_eq_billing_address
      - cart_id
      - channel_id
      - company_id
      - company_name
      - po_document_filename
      - po_document_byte_size
      - number
      - email
      - customer_note
      - po_number
      - currency
      - locale
      - total_quantity
      - coupon_code
      - fulfillment_status
      - payment_status
      - completed_at
      - item_total
      - discount_total
      - tax_total
      - included_tax_total
      - additional_tax_total
      - delivery_total
      - fee_total
      - gift_card_total
      - store_credit_total
      - total
      - amount_due
      - covered_by_store_credit
      - adjustment_total
      - gift_card
      - market
      - external_references
      - status
      - last_ip_address
      - considered_risky
      - confirmation_delivered
      - store_owner_notification_delivered
      - metadata
      - cancel_note
      - canceled_at
      - approved_at
      - created_at
      - updated_at
      - payment_total
      - commission_amount_total
      - commission_tax_total
      - commission_total
      - preferred_stock_location_id
      - po_document_url
      - seller_id
      - order_group_id
      - tags
      - internal_note
      - internal_note_html
      - approver_id
      - approver_type
      - canceler_id
      - canceler_type
      - created_by_id
      - created_by_type
      - cancel_reason_id
      - cancel_reason_name
      - customer_id
      - freight_summary
      x-typelizer: true
    PackageType:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        kind:
          type: string
          enum:
          - box
          - envelope
          - carton
          - pallet
          - container
        length:
          type: string
          nullable: true
        width:
          type: string
          nullable: true
        height:
          type: string
          nullable: true
        weight:
          type: string
          nullable: true
        max_weight:
          type: string
          nullable: true
        default:
          type: boolean
        metadata:
          type: object
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        dimensions_unit:
          type: string
          enum:
          - mm
          - cm
          - in
          - ft
        weight_unit:
          type: string
          enum:
          - g
          - kg
          - lb
          - oz
        volume:
          type: string
          nullable: true
        seller_id:
          type: string
          nullable: true
        seller_name:
          type: string
          nullable: true
      required:
      - id
      - name
      - kind
      - length
      - width
      - height
      - weight
      - max_weight
      - default
      - metadata
      - created_at
      - updated_at
      - dimensions_unit
      - weight_unit
      - volume
      - seller_id
      - seller_name
      x-typelizer: true
    PaymentCaptureEvent:
      type: object
      properties:
        id:
          type: string
        created_at:
          type: string
        updated_at:
          type: string
        amount:
          type: string
      required:
      - id
      - created_at
      - updated_at
      - amount
      x-typelizer: true
    PaymentMethod:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
          nullable: true
        type:
          type: string
          description: 'Payment method type. Built-in: check, store_credit, custom_payment_source_method,
            bogus (test only); payment provider gems register their own, for example
            stripe.'
        session_required:
          type: boolean
        source_required:
          type: boolean
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        metadata:
          type: object
        active:
          type: boolean
        capture_method:
          type: string
          enum:
          - checkout
          - on_dispatch
          - manual
          nullable: true
        resolved_capture_method:
          type: string
          enum:
          - checkout
          - on_dispatch
          - manual
        storefront_visible:
          type: boolean
        position:
          type: number
        created_at:
          type: string
        updated_at:
          type: string
        preferences:
          "$ref": "#/components/schemas/PaymentMethodPreferences"
        logo_url:
          type: string
          nullable: true
        docs_url:
          type: string
          nullable: true
        third_party:
          type: boolean
      required:
      - id
      - name
      - description
      - type
      - session_required
      - source_required
      - metadata
      - active
      - capture_method
      - resolved_capture_method
      - storefront_visible
      - position
      - created_at
      - updated_at
      - preferences
      - logo_url
      - docs_url
      - third_party
      x-typelizer: true
    Payment:
      type: object
      properties:
        id:
          type: string
        payment_method_id:
          type: string
        response_code:
          type: string
          nullable: true
        number:
          type: string
        status:
          anyOf:
          - type: string
            enum:
            - checkout
            - processing
            - pending
            - completed
            - failed
            - void
            - invalid
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        amount:
          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"
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        metadata:
          type: object
        avs_response:
          type: string
          nullable: true
        cvv_response_code:
          type: string
          nullable: true
        cvv_response_message:
          type: string
          nullable: true
        gateway_dashboard_payment_url:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        avs_risky:
          type: boolean
          description: Whether the card issuer reported that the billing address did
            not match.
        cvv_risky:
          type: boolean
          description: Whether the card issuer reported that the security code did
            not match.
        can_void:
          type: boolean
          description: Whether the payment can be voided now, as decided by its payment
            method.
        can_capture:
          type: boolean
          description: Whether the payment can be captured now, as decided by its
            payment method.
        captured_amount:
          type: string
        order_id:
          type: string
          nullable: true
        capture_events:
          type: array
          items:
            "$ref": "#/components/schemas/PaymentCaptureEvent"
        order:
          "$ref": "#/components/schemas/Order"
        refunds:
          type: array
          items:
            "$ref": "#/components/schemas/Refund"
        payment_splits:
          type: array
          items:
            "$ref": "#/components/schemas/PaymentSplit"
      required:
      - id
      - payment_method_id
      - response_code
      - number
      - status
      - amount
      - source_type
      - source_id
      - source
      - metadata
      - avs_response
      - cvv_response_code
      - cvv_response_message
      - gateway_dashboard_payment_url
      - created_at
      - updated_at
      - avs_risky
      - cvv_risky
      - can_void
      - can_capture
      - captured_amount
      - order_id
      x-typelizer: true
    PaymentSource:
      type: object
      properties:
        id:
          type: string
        gateway_payment_profile_id:
          type: string
          nullable: true
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        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
    PaymentSplit:
      type: object
      properties:
        id:
          type: string
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        created_at:
          type: string
        updated_at:
          type: string
        authorized_amount:
          type: string
        captured_amount:
          type: string
        refunded_amount:
          type: string
        claimed_amount:
          type: string
        net_captured_amount:
          type: string
        refundable_amount:
          type: string
        payment_id:
          type: string
        payment_number:
          type: string
          nullable: true
        order_id:
          type: string
        order_number:
          type: string
          nullable: true
      required:
      - id
      - currency
      - created_at
      - updated_at
      - authorized_amount
      - captured_amount
      - refunded_amount
      - claimed_amount
      - net_captured_amount
      - refundable_amount
      - payment_id
      - payment_number
      - order_id
      - order_number
      x-typelizer: true
    Permission:
      type: object
      properties:
        key:
          type: string
        resource:
          type: string
        kind:
          type: string
          enum:
          - read
          - write
        group:
          type: string
        group_label:
          type: string
        label:
          type: string
        description:
          type: string
      required:
      - key
      - resource
      - kind
      - group
      - group_label
      - label
      - description
      x-typelizer: true
    Policy:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        slug:
          type: string
        body:
          type: string
          nullable: true
        body_html:
          type: string
          nullable: true
        updated_at:
          type: string
        created_at:
          type: string
      required:
      - id
      - name
      - slug
      - body
      - body_html
      - updated_at
      - created_at
      x-typelizer: true
    PriceAdjustmentTier:
      type: object
      properties:
        id:
          type: string
        min_quantity:
          type: number
        percentage:
          type: string
      required:
      - id
      - min_quantity
      - percentage
      x-typelizer: true
    PriceHistory:
      type: object
      properties:
        id:
          type: string
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        amount:
          type: string
          nullable: true
        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
      - currency
      - amount
      - recorded_at
      - variant_id
      - price_id
      - compare_at_amount
      - created_at
      x-typelizer: true
    PriceListProduct:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        thumbnail_url:
          type: string
          nullable: true
        price_list_variants:
          type: array
          items:
            "$ref": "#/components/schemas/CatalogPrice"
      required:
      - id
      - name
      - thumbnail_url
      x-typelizer: true
    PriceList:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
          nullable: true
        status:
          anyOf:
          - type: string
            enum:
            - draft
            - active
            - inactive
            - scheduled
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        position:
          type: number
        match_policy:
          type: string
          enum:
          - all
          - any
        adjust_compare_at:
          type: boolean
        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
        price_adjustment_percentage:
          type: string
          nullable: true
        automatic_pricing:
          type: boolean
        currently_active:
          type: boolean
        products_count:
          type: number
        prices_count:
          type: number
        price_adjustment_tiers:
          type: array
          items:
            "$ref": "#/components/schemas/PriceAdjustmentTier"
        price_rules:
          type: array
          items:
            "$ref": "#/components/schemas/PriceRule"
      required:
      - id
      - name
      - description
      - status
      - position
      - match_policy
      - adjust_compare_at
      - starts_at
      - ends_at
      - deleted_at
      - created_at
      - updated_at
      - price_adjustment_percentage
      - automatic_pricing
      - currently_active
      - products_count
      - prices_count
      - price_adjustment_tiers
      x-typelizer: true
    PriceRule:
      type: object
      properties:
        id:
          type: string
        created_at:
          type: string
        updated_at:
          type: string
        type:
          type: string
          description: 'Rule type. Built-in: channel_rule, customer_group_rule, market_rule,
            user_rule, volume_rule, zone_rule. Extensions may register more.'
        price_list_id:
          type: string
        preferences:
          "$ref": "#/components/schemas/PriceRulePreferences"
        markets:
          type: array
          items:
            "$ref": "#/components/schemas/Market"
        customer_groups:
          type: array
          items:
            "$ref": "#/components/schemas/CustomerGroup"
        channels:
          type: array
          items:
            "$ref": "#/components/schemas/Channel"
        customers:
          type: array
          items:
            "$ref": "#/components/schemas/Customer"
      required:
      - id
      - created_at
      - updated_at
      - type
      - price_list_id
      - preferences
      x-typelizer: true
    Price:
      type: object
      properties:
        id:
          type: string
        currency:
          type: string
          nullable: true
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        amount:
          type: string
          nullable: true
        compare_at_amount:
          type: string
          nullable: true
        price_list_id:
          type: string
          nullable: true
        min_quantity:
          type: number
        variant_id:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        variant:
          "$ref": "#/components/schemas/Variant"
      required:
      - id
      - currency
      - amount
      - compare_at_amount
      - price_list_id
      - min_quantity
      - 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
        preorder_ships_at:
          type: string
          nullable: true
        purchasable:
          type: boolean
        preorder:
          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
        buy_box_variant_id:
          type: string
          nullable: true
        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
        seller_id:
          type: string
          nullable: true
        seller:
          "$ref": "#/components/schemas/Seller"
        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
        external_references:
          type: object
        translations:
          type: object
        status:
          anyOf:
          - type: string
            enum:
            - draft
            - active
            - archived
            - proposed
            - rejected
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        metadata:
          type: object
        deleted_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        delivery_profile_id:
          type: string
          nullable: true
        submission:
          allOf:
          - "$ref": "#/components/schemas/ProductSubmission"
          nullable: true
        seller_name:
          type: string
          nullable: true
        product_type_id:
          type: string
          nullable: true
        tax_category_id:
          type: string
          nullable: true
        total_on_hand:
          type: number
          nullable: true
        digital_assets:
          type: array
          items:
            "$ref": "#/components/schemas/DigitalAsset"
        collections:
          type: array
          items:
            "$ref": "#/components/schemas/Collection"
        product_publications:
          type: array
          items:
            "$ref": "#/components/schemas/ProductPublication"
        channels:
          type: array
          items:
            "$ref": "#/components/schemas/Channel"
        product_type:
          "$ref": "#/components/schemas/ProductType"
      required:
      - id
      - name
      - slug
      - meta_title
      - meta_description
      - meta_keywords
      - variant_count
      - available_on
      - preorder_ships_at
      - purchasable
      - preorder
      - in_stock
      - backorderable
      - available
      - description
      - description_html
      - default_variant_id
      - buy_box_variant_id
      - thumbnail_url
      - tags
      - price
      - original_price
      - seller_id
      - external_references
      - status
      - metadata
      - deleted_at
      - created_at
      - updated_at
      - delivery_profile_id
      - seller_name
      - product_type_id
      - tax_category_id
      - total_on_hand
      x-typelizer: true
    ProductSubmission:
      type: object
      properties:
        id:
          type: string
        status:
          anyOf:
          - type: string
            enum:
            - pending
            - approved
            - rejected
            - withdrawn
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        review_note:
          type: string
          nullable: true
        reviewed_at:
          type: string
          nullable: true
        created_at:
          type: string
        product_id:
          type: string
        metadata:
          type: object
          nullable: true
        updated_at:
          type: string
        submitted_by_id:
          type: string
          nullable: true
        reviewed_by_id:
          type: string
          nullable: true
        reviewed_by_name:
          type: string
          nullable: true
        auto_approved:
          type: boolean
      required:
      - id
      - status
      - review_note
      - reviewed_at
      - created_at
      - product_id
      - metadata
      - updated_at
      - submitted_by_id
      - reviewed_by_id
      - reviewed_by_name
      - auto_approved
      x-typelizer: true
    ProductTypeCustomFieldDefinition:
      type: object
      properties:
        id:
          type: string
        key:
          type: string
        namespace:
          type: string
        label:
          type: string
        field_type:
          type: string
          enum:
          - short_text
          - long_text
          - rich_text
          - number
          - boolean
          - json
        required:
          type: boolean
        sort_order:
          type: number
      required:
      - id
      - key
      - namespace
      - label
      - field_type
      - required
      - sort_order
      x-typelizer: true
    ProductType:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        translations:
          type: object
        products_count:
          type: number
        created_at:
          type: string
        updated_at:
          type: string
        delivery_profile_id:
          type: string
          nullable: true
        option_type_ids:
          type: array
          items:
            type: string
        category_ids:
          type: array
          items:
            type: string
        custom_field_definitions:
          type: array
          items:
            "$ref": "#/components/schemas/ProductTypeCustomFieldDefinition"
      required:
      - id
      - name
      - products_count
      - created_at
      - updated_at
      - delivery_profile_id
      - option_type_ids
      - category_ids
      - custom_field_definitions
      x-typelizer: true
    PromotionAction:
      type: object
      properties:
        id:
          type: string
        created_at:
          type: string
        updated_at:
          type: string
        type:
          type: string
          description: 'Action type. Built-in: create_adjustment, create_item_adjustments,
            create_line_items, free_shipping. Extensions may register more.'
        promotion_id:
          type: string
        preferences:
          type: object
        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
      - calculator
      - line_items
      x-typelizer: true
    PromotionRule:
      type: object
      properties:
        id:
          type: string
        created_at:
          type: string
        updated_at:
          type: string
        type:
          type: string
          description: 'Rule type. Built-in: currency, country, channel, market, item_total,
            product, customer, customer_group, first_order, customer_logged_in, one_use_per_user,
            category, option_value. Extensions may register more.'
        promotion_id:
          type: string
        preferences:
          "$ref": "#/components/schemas/PromotionRulePreferences"
        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
        option_value_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"
        channels:
          type: array
          items:
            "$ref": "#/components/schemas/Channel"
        markets:
          type: array
          items:
            "$ref": "#/components/schemas/Market"
        option_values:
          type: array
          items:
            "$ref": "#/components/schemas/OptionValue"
      required:
      - id
      - created_at
      - updated_at
      - type
      - promotion_id
      - preferences
      - product_ids
      - category_ids
      - customer_ids
      - option_value_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
        rules:
          type: array
          items:
            "$ref": "#/components/schemas/PromotionRule"
        actions:
          type: array
          items:
            "$ref": "#/components/schemas/PromotionAction"
      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
    PurchaseOrderItem:
      type: object
      properties:
        id:
          type: string
        quantity_ordered:
          type: number
        quantity_received:
          type: number
        quantity_rejected:
          type: number
        quantity_over:
          type: number
        outstanding:
          type: number
        currency:
          type: string
          nullable: true
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        created_at:
          type: string
        updated_at:
          type: string
        unit_cost:
          type: string
        total_cost:
          type: string
        purchase_order_id:
          type: string
          nullable: true
        variant_id:
          type: string
          nullable: true
        product_id:
          type: string
          nullable: true
        variant_name:
          type: string
          nullable: true
        variant_sku:
          type: string
          nullable: true
        options_text:
          type: string
          nullable: true
        thumbnail_url:
          type: string
          nullable: true
      required:
      - id
      - quantity_ordered
      - quantity_received
      - quantity_rejected
      - quantity_over
      - outstanding
      - currency
      - created_at
      - updated_at
      - unit_cost
      - total_cost
      - purchase_order_id
      - variant_id
      - product_id
      - variant_name
      - variant_sku
      - options_text
      - thumbnail_url
      x-typelizer: true
    PurchaseOrder:
      type: object
      properties:
        id:
          type: string
        number:
          type: string
        status:
          anyOf:
          - type: string
            enum:
            - draft
            - ordered
            - partially_received
            - received
            - over_received
            - canceled
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        reference:
          type: string
          nullable: true
        notes:
          type: string
          nullable: true
        metadata:
          type: object
        close_reason:
          type: string
          nullable: true
        items_count:
          type: number
        quantity_received_total:
          type: number
        quantity_rejected_total:
          type: number
        ordered_at:
          type: string
          nullable: true
        received_at:
          type: string
          nullable: true
        closed_short_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        expected_at:
          type: string
          nullable: true
        cancel_by:
          type: string
          nullable: true
        closed_short:
          type: boolean
        quantity_ordered_total:
          type: number
        editable:
          type: boolean
        subtotal:
          type: string
        supplier_id:
          type: string
          nullable: true
        destination_location_id:
          type: string
          nullable: true
        items:
          type: array
          items:
            "$ref": "#/components/schemas/PurchaseOrderItem"
        stock_receipts:
          type: array
          items:
            "$ref": "#/components/schemas/StockReceipt"
        supplier:
          "$ref": "#/components/schemas/Supplier"
        destination_location:
          "$ref": "#/components/schemas/StockLocation"
      required:
      - id
      - number
      - status
      - currency
      - reference
      - notes
      - metadata
      - close_reason
      - items_count
      - quantity_received_total
      - quantity_rejected_total
      - ordered_at
      - received_at
      - closed_short_at
      - created_at
      - updated_at
      - expected_at
      - cancel_by
      - closed_short
      - quantity_ordered_total
      - editable
      - subtotal
      - supplier_id
      - destination_location_id
      x-typelizer: true
    RefundReason:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        active:
          type: boolean
        created_at:
          type: string
        updated_at:
          type: string
        can_be_deleted:
          type: boolean
      required:
      - id
      - name
      - active
      - created_at
      - updated_at
      - can_be_deleted
      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
        originator_id:
          type: string
          nullable: true
        originator_type:
          type: string
          nullable: true
        metadata:
          type: object
        created_at:
          type: string
        updated_at:
          type: string
        tax_amount:
          type: string
        refunder_id:
          type: string
          nullable: true
        refunder_type:
          anyOf:
          - type: string
            enum:
            - admin_user
            - api_key
          - type: string
            nullable: true
          description: The values listed are the built-in ones; extensions may add
            more.
        refunder:
          "$ref": "#/components/schemas/Actor"
        payment:
          "$ref": "#/components/schemas/Payment"
      required:
      - id
      - transaction_id
      - amount
      - payment_id
      - refund_reason_id
      - originator_id
      - originator_type
      - metadata
      - created_at
      - updated_at
      - tax_amount
      - refunder_id
      - refunder_type
      x-typelizer: true
    ReturnLineItem:
      type: object
      properties:
        id:
          type: string
        quantity:
          type: number
        received_quantity:
          type: number
        resellable:
          type: boolean
        pre_tax_amount:
          type: string
        included_tax_total:
          type: string
        additional_tax_total:
          type: string
        tax_total:
          type: string
        refund_amount:
          type: string
        variant_id:
          type: string
          nullable: true
        line_item_id:
          type: string
          nullable: true
        fulfillment_item_id:
          type: string
          nullable: true
        variant:
          "$ref": "#/components/schemas/Variant"
        created_at:
          type: string
        updated_at:
          type: string
        line_item:
          "$ref": "#/components/schemas/LineItem"
        tax_lines:
          type: array
          items:
            "$ref": "#/components/schemas/TaxLine"
      required:
      - id
      - quantity
      - received_quantity
      - resellable
      - pre_tax_amount
      - included_tax_total
      - additional_tax_total
      - tax_total
      - refund_amount
      - variant_id
      - line_item_id
      - fulfillment_item_id
      - created_at
      - updated_at
      x-typelizer: true
    ReturnReason:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        active:
          type: boolean
        created_at:
          type: string
        updated_at:
          type: string
        can_be_deleted:
          type: boolean
      required:
      - id
      - name
      - active
      - created_at
      - updated_at
      - can_be_deleted
      x-typelizer: true
    Return:
      type: object
      properties:
        id:
          type: string
        number:
          type: string
        status:
          anyOf:
          - type: string
            enum:
            - requested
            - approved
            - received
            - refunded
            - canceled
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        order_id:
          type: string
          nullable: true
        reason_id:
          type: string
          nullable: true
        refund_total:
          type: string
        refund_tax_total:
          type: string
        approved_at:
          type: string
          nullable: true
        received_at:
          type: string
          nullable: true
        refunded_at:
          type: string
          nullable: true
        canceled_at:
          type: string
          nullable: true
        reason:
          "$ref": "#/components/schemas/ReturnReason"
        return_line_items:
          type: array
          items:
            "$ref": "#/components/schemas/ReturnLineItem"
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        external_references:
          type: object
        memo:
          type: string
          nullable: true
        metadata:
          type: object
        created_at:
          type: string
        updated_at:
          type: string
        stock_location_id:
          type: string
          nullable: true
        created_by_id:
          type: string
          nullable: true
        created_by_type:
          anyOf:
          - type: string
            enum:
            - admin_user
            - api_key
          - type: string
            nullable: true
          description: The values listed are the built-in ones; extensions may add
            more.
        created_by:
          "$ref": "#/components/schemas/Actor"
        refunded_total:
          type: string
        refundable_total:
          type: string
        order:
          "$ref": "#/components/schemas/Order"
        stock_location:
          "$ref": "#/components/schemas/StockLocation"
        refunds:
          type: array
          items:
            "$ref": "#/components/schemas/Refund"
        documents:
          type: array
          items:
            type: object
            properties:
              kind:
                type: string
              url:
                type: string
            required:
            - kind
            - url
        labels:
          type: array
          items:
            "$ref": "#/components/schemas/ShippingLabel"
        deliveries:
          type: array
          items:
            "$ref": "#/components/schemas/Delivery"
      required:
      - id
      - number
      - status
      - order_id
      - reason_id
      - refund_total
      - refund_tax_total
      - approved_at
      - received_at
      - refunded_at
      - canceled_at
      - external_references
      - memo
      - metadata
      - created_at
      - updated_at
      - stock_location_id
      - created_by_id
      - created_by_type
      - refunded_total
      - refundable_total
      - documents
      - labels
      - deliveries
      x-typelizer: true
    Role:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        permissions:
          type: array
          items:
            type: string
        mutable:
          type: boolean
        users_count:
          type: number
      required:
      - id
      - name
      - description
      - created_at
      - updated_at
      - permissions
      - mutable
      - users_count
      x-typelizer: true
    SavedReport:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        description:
          type: string
          nullable: true
        query:
          type: object
        seeded:
          type: boolean
        created_at:
          type: string
        updated_at:
          type: string
        user_id:
          type: string
          nullable: true
        author_name:
          type: string
          nullable: true
      required:
      - id
      - name
      - description
      - query
      - seeded
      - created_at
      - updated_at
      - user_id
      - author_name
      x-typelizer: true
    SellerBalance:
      type: object
      properties:
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        settlement_currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        converted:
          type: boolean
        seller_id:
          type: string
        earned:
          type: string
        pending:
          type: string
        payable:
          type: string
        paid:
          type: string
        balance:
          type: string
      required:
      - currency
      - settlement_currency
      - converted
      - seller_id
      - earned
      - pending
      - payable
      - paid
      - balance
      x-typelizer: true
    SellerPayout:
      type: object
      properties:
        id:
          type: string
        status:
          anyOf:
          - type: string
            enum:
            - pending
            - processing
            - completed
            - failed
            - unresolved
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        reference:
          type: string
          nullable: true
        metadata:
          type: object
        period_start:
          type: string
          nullable: true
        period_end:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        amount:
          type: string
        seller_id:
          type: string
        seller_name:
          type: string
          nullable: true
        transfers_count:
          type: number
        provider:
          type: string
          description: 'Payout provider. Built-in: system. Provider gems register
            more (e.g. stripe).'
      required:
      - id
      - status
      - currency
      - reference
      - metadata
      - period_start
      - period_end
      - created_at
      - updated_at
      - amount
      - seller_id
      - seller_name
      - transfers_count
      - provider
      x-typelizer: true
    SellerRequirement:
      type: object
      properties:
        id:
          type: string
        position:
          type: number
        active:
          type: boolean
        required:
          type: boolean
        metadata:
          type: object
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        kind:
          type: string
          description: 'Requirement kind. Built-in: accept_terms, complete_profile,
            billing_address, returns_address, delivery_method, package_type, minimum_products,
            payout_account, required_custom_fields, policy, attestation, operator_review,
            document. Extensions may register more.'
        name:
          type: string
        description:
          type: string
          nullable: true
        preferences:
          "$ref": "#/components/schemas/SellerRequirementPreferences"
        custom_field_definition_ids:
          type: array
          items:
            type: string
        allow_multiple:
          type: boolean
        accepts_submissions:
          type: boolean
        reviewed_by_operator:
          type: boolean
      required:
      - id
      - position
      - active
      - required
      - metadata
      - created_at
      - updated_at
      - kind
      - name
      - description
      - preferences
      - custom_field_definition_ids
      - allow_multiple
      - accepts_submissions
      - reviewed_by_operator
      x-typelizer: true
    SellerRequirementStatus:
      type: object
      properties:
        id:
          type: string
        kind:
          type: string
          description: 'Requirement kind. Built-in: accept_terms, complete_profile,
            billing_address, returns_address, delivery_method, package_type, minimum_products,
            payout_account, required_custom_fields, policy, attestation, operator_review,
            document. Extensions may register more.'
        name:
          type: string
        description:
          type: string
          nullable: true
        required:
          type: boolean
        position:
          type: number
        status:
          type: string
          enum:
          - complete
          - incomplete
          - pending
          - rejected
        action_url:
          type: string
          nullable: true
        blocker:
          type: object
          properties:
            state:
              type: string
            message:
              type: string
              nullable: true
          required:
          - state
          - message
          nullable: true
        blocking:
          type: boolean
        required_policy_name:
          type: string
          nullable: true
        submission:
          "$ref": "#/components/schemas/SellerRequirementSubmission"
        published_policy:
          "$ref": "#/components/schemas/Policy"
      required:
      - id
      - kind
      - name
      - description
      - required
      - position
      - status
      - action_url
      - blocker
      - blocking
      - required_policy_name
      x-typelizer: true
    SellerRequirementSubmission:
      type: object
      properties:
        id:
          type: string
        status:
          anyOf:
          - type: string
            enum:
            - pending
            - accepted
            - rejected
            - waived
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        note:
          type: string
          nullable: true
        review_note:
          type: string
          nullable: true
        reference:
          type: string
          nullable: true
        metadata:
          type: object
          nullable: true
        reviewed_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        seller_id:
          type: string
        requirement_id:
          type: string
        requirement_name:
          type: string
        file_url:
          type: string
          nullable: true
        file_name:
          type: string
          nullable: true
      required:
      - id
      - status
      - note
      - review_note
      - reference
      - metadata
      - reviewed_at
      - created_at
      - updated_at
      - seller_id
      - requirement_id
      - requirement_name
      - file_url
      - file_name
      x-typelizer: true
    Seller:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        slug:
          type: string
        about:
          type: string
        about_html:
          type: string
        logo_url:
          type: string
          nullable: true
        square_logo_url:
          type: string
          nullable: true
        cover_photo_url:
          type: string
          nullable: true
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        external_references:
          type: object
        status:
          anyOf:
          - type: string
            enum:
            - pending
            - invited
            - canceled
            - onboarding
            - ready_for_review
            - approved
            - rejected
            - suspended
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        contact_email:
          type: string
          nullable: true
        billing_email:
          type: string
          nullable: true
        tax_remittance:
          type: string
          enum:
          - seller
          - platform
        payouts_schedule_interval:
          type: string
          nullable: true
          enum:
          - daily
          - weekly
          - biweekly
          - monthly
          - manual
        metadata:
          type: object
          nullable: true
        holiday_mode_until:
          type: string
          nullable: true
        terms_accepted_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        deleted_at:
          type: string
          nullable: true
        minimum_payout_amount:
          type: string
          nullable: true
        on_holiday:
          type: boolean
        sellable:
          type: boolean
        products_count:
          type: number
        users_count:
          type: number
        onboarding_progress:
          type: object
          properties:
            done:
              type: number
            total:
              type: number
          required:
          - done
          - total
        onboarding_complete:
          type: boolean
        legal_name:
          type: string
          nullable: true
        registration_number:
          type: string
          nullable: true
        billing_address:
          "$ref": "#/components/schemas/Address"
        returns_address:
          "$ref": "#/components/schemas/Address"
        returns_location_id:
          type: string
          nullable: true
      required:
      - id
      - name
      - slug
      - about
      - about_html
      - logo_url
      - square_logo_url
      - cover_photo_url
      - external_references
      - status
      - contact_email
      - billing_email
      - tax_remittance
      - payouts_schedule_interval
      - metadata
      - holiday_mode_until
      - terms_accepted_at
      - created_at
      - updated_at
      - deleted_at
      - minimum_payout_amount
      - on_holiday
      - sellable
      - products_count
      - users_count
      - onboarding_progress
      - onboarding_complete
      - legal_name
      - registration_number
      - returns_location_id
      x-typelizer: true
    SellerTeamMember:
      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
        avatar_url:
          type: string
          nullable: true
      required:
      - id
      - email
      - first_name
      - last_name
      - full_name
      - created_at
      - updated_at
      - avatar_url
      x-typelizer: true
    SellerTransfer:
      type: object
      properties:
        id:
          type: string
        kind:
          type: string
          enum:
          - earning
          - refund_reversal
        status:
          anyOf:
          - type: string
            enum:
            - pending
            - processing
            - completed
            - failed
            - unresolved
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        reference:
          type: string
          nullable: true
        metadata:
          type: object
        created_at:
          type: string
        updated_at:
          type: string
        amount:
          type: string
        settled_amount:
          type: string
          nullable: true
        settled_currency:
          type: string
          nullable: true
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        converted:
          type: boolean
        seller_id:
          type: string
        order_id:
          type: string
          nullable: true
        payout_id:
          type: string
          nullable: true
        reversed_from_id:
          type: string
          nullable: true
        refund_id:
          type: string
          nullable: true
        seller_name:
          type: string
          nullable: true
        order_number:
          type: string
          nullable: true
        provider:
          type: string
          description: 'Payout provider. Built-in: system. Provider gems register
            more (e.g. stripe).'
      required:
      - id
      - kind
      - status
      - currency
      - reference
      - metadata
      - created_at
      - updated_at
      - amount
      - settled_amount
      - settled_currency
      - converted
      - seller_id
      - order_id
      - payout_id
      - reversed_from_id
      - refund_id
      - seller_name
      - order_number
      - provider
      x-typelizer: true
    Session:
      type: object
      properties:
        id:
          type: string
        ip_address:
          type: string
          nullable: true
        user_agent:
          type: string
          nullable: true
        last_active_at:
          type: string
      required:
      - id
      - ip_address
      - user_agent
      - last_active_at
      x-typelizer: true
    SetupTask:
      type: object
      properties:
        name:
          type: string
        done:
          type: boolean
      required:
      - name
      - done
      x-typelizer: true
    ShippingLabel:
      type: object
      properties:
        id:
          type: string
        source:
          type: string
          enum:
          - purchased
          - uploaded
        status:
          anyOf:
          - type: string
            enum:
            - purchased
            - refund_requested
            - refunded
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        carrier:
          type: string
          nullable: true
        carrier_name:
          type: string
          nullable: true
        service:
          type: string
          nullable: true
        tracking_number:
          type: string
          nullable: true
        currency:
          type: string
          nullable: true
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        format:
          type: string
          nullable: true
          enum:
          - pdf
          - png
          - zpl
        external_id:
          type: string
          nullable: true
        metadata:
          type: object
        refunded_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        owner_id:
          type: string
        owner_type:
          type: string
          enum:
          - fulfillment
          - return
        cost:
          type: string
        integration_id:
          type: string
          nullable: true
        file_pending:
          type: boolean
        download_url:
          type: string
          nullable: true
      required:
      - id
      - source
      - status
      - carrier
      - carrier_name
      - service
      - tracking_number
      - currency
      - format
      - external_id
      - metadata
      - refunded_at
      - created_at
      - updated_at
      - owner_id
      - owner_type
      - cost
      - integration_id
      - file_pending
      - download_url
      x-typelizer: true
    State:
      type: object
      properties:
        abbr:
          type: string
        name:
          type: string
      required:
      - abbr
      - name
      x-typelizer: true
    StockLevel:
      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
        external_references:
          type: object
        metadata:
          type: object
        reserved_count:
          type: number
        incoming_count:
          type: number
        purchasable_count:
          type: number
        variant_name:
          type: string
          nullable: true
        variant_sku:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        stock_location_name:
          type: string
          nullable: true
        product_id:
          type: string
          nullable: true
        options_text:
          type: string
          nullable: true
        thumbnail_url:
          type: string
          nullable: true
        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
      - external_references
      - metadata
      - reserved_count
      - incoming_count
      - purchasable_count
      - variant_name
      - variant_sku
      - created_at
      - updated_at
      - stock_location_name
      - product_id
      - options_text
      - thumbnail_url
      - allocated_count
      - available_count
      x-typelizer: true
    StockLocation:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        address1:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        zipcode:
          type: string
          nullable: true
        country_code:
          type: string
          nullable: true
          enum:
          - AD
          - AE
          - AF
          - AG
          - AI
          - AL
          - AM
          - AO
          - AR
          - AS
          - AT
          - AU
          - AW
          - AZ
          - BA
          - BB
          - BD
          - BE
          - BF
          - BG
          - BH
          - BI
          - BJ
          - BL
          - BM
          - BN
          - BO
          - BQ
          - BR
          - BS
          - BT
          - BW
          - BY
          - BZ
          - CA
          - CC
          - CD
          - CF
          - CG
          - CH
          - CI
          - CK
          - CL
          - CM
          - CN
          - CO
          - CR
          - CU
          - CV
          - CW
          - CX
          - CY
          - CZ
          - DE
          - DJ
          - DK
          - DM
          - DO
          - DZ
          - EC
          - EE
          - EG
          - ER
          - ES
          - ET
          - FI
          - FJ
          - FK
          - FM
          - FO
          - FR
          - GA
          - GB
          - GD
          - GE
          - GF
          - GG
          - GH
          - GI
          - GL
          - GM
          - GN
          - GP
          - GQ
          - GR
          - GT
          - GU
          - GW
          - GY
          - HK
          - HN
          - HR
          - HT
          - HU
          - ID
          - IE
          - IL
          - IM
          - IN
          - IQ
          - IR
          - IS
          - IT
          - JE
          - JM
          - JO
          - JP
          - KE
          - KG
          - KH
          - KI
          - KM
          - KN
          - KP
          - KR
          - KW
          - KY
          - KZ
          - LA
          - LB
          - LC
          - LI
          - LK
          - LR
          - LS
          - LT
          - LU
          - LV
          - LY
          - MA
          - MC
          - MD
          - ME
          - MF
          - MG
          - MH
          - MK
          - ML
          - MM
          - MN
          - MO
          - MP
          - MQ
          - MR
          - MS
          - MT
          - MU
          - MV
          - MW
          - MX
          - MY
          - MZ
          - NA
          - NC
          - NE
          - NF
          - NG
          - NI
          - NL
          - 'NO'
          - NP
          - NR
          - NU
          - NZ
          - OM
          - PA
          - PE
          - PF
          - PG
          - PH
          - PK
          - PL
          - PM
          - PN
          - PR
          - PS
          - PT
          - PW
          - PY
          - QA
          - RE
          - RO
          - RS
          - RU
          - RW
          - SA
          - SB
          - SC
          - SD
          - SE
          - SG
          - SH
          - SI
          - SJ
          - SK
          - SL
          - SM
          - SN
          - SO
          - SR
          - SS
          - ST
          - SV
          - SX
          - SY
          - SZ
          - TC
          - TD
          - TG
          - TH
          - TJ
          - TK
          - TL
          - TM
          - TN
          - TO
          - TR
          - TT
          - TV
          - TW
          - TZ
          - UA
          - UG
          - US
          - UY
          - UZ
          - VA
          - VC
          - VE
          - VG
          - VI
          - VN
          - VU
          - WF
          - WS
          - YE
          - YT
          - ZA
          - ZM
          - ZW
        country_name:
          type: string
          nullable: true
        state_code:
          type: string
          nullable: true
        state_text:
          type: string
          nullable: true
        pickup_ready_in_minutes:
          type: number
          nullable: true
        pickup_instructions:
          type: string
          nullable: true
        external_references:
          type: object
        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:
          anyOf:
          - type: string
            enum:
            - warehouse
            - store
            - fulfillment_center
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        pickup_enabled:
          type: boolean
        pickup_stock_policy:
          type: string
          enum:
          - local
          - any
        returns_enabled:
          type: boolean
        created_at:
          type: string
        updated_at:
          type: string
        seller_id:
          type: string
          nullable: true
        seller_name:
          type: string
          nullable: true
        seller:
          "$ref": "#/components/schemas/Seller"
      required:
      - id
      - name
      - address1
      - city
      - zipcode
      - country_code
      - country_name
      - state_code
      - state_text
      - pickup_ready_in_minutes
      - pickup_instructions
      - external_references
      - admin_name
      - address2
      - state_name
      - phone
      - company
      - active
      - default
      - backorderable_default
      - propagate_all_variants
      - kind
      - pickup_enabled
      - pickup_stock_policy
      - returns_enabled
      - created_at
      - updated_at
      - seller_id
      - seller_name
      x-typelizer: true
    StockMovement:
      type: object
      properties:
        id:
          type: string
        quantity:
          type: number
        kind:
          type: string
          nullable: true
          enum:
          - received
          - allocated
          - shipped
          - released
          - adjusted
        reason:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        stock_level_id:
          type: string
          nullable: true
        stock_location_id:
          type: string
          nullable: true
        stock_location_name:
          type: string
          nullable: true
        variant_id:
          type: string
          nullable: true
        variant_name:
          type: string
          nullable: true
        variant_sku:
          type: string
          nullable: true
        order_id:
          type: string
          nullable: true
        fulfillment_id:
          type: string
          nullable: true
        return_id:
          type: string
          nullable: true
        exchange_id:
          type: string
          nullable: true
        stock_transfer_id:
          type: string
          nullable: true
        stock_receipt_id:
          type: string
          nullable: true
        purchase_order_id:
          type: string
          nullable: true
        order_number:
          type: string
          nullable: true
        return_number:
          type: string
          nullable: true
        exchange_number:
          type: string
          nullable: true
        stock_transfer_number:
          type: string
          nullable: true
        purchase_order_number:
          type: string
          nullable: true
        unit_cost:
          type: string
          nullable: true
      required:
      - id
      - quantity
      - kind
      - reason
      - created_at
      - updated_at
      - stock_level_id
      - stock_location_id
      - stock_location_name
      - variant_id
      - variant_name
      - variant_sku
      - order_id
      - fulfillment_id
      - return_id
      - exchange_id
      - stock_transfer_id
      - stock_receipt_id
      - purchase_order_id
      - order_number
      - return_number
      - exchange_number
      - stock_transfer_number
      - purchase_order_number
      - unit_cost
      x-typelizer: true
    StockReceiptItem:
      type: object
      properties:
        id:
          type: string
        quantity_accepted:
          type: number
        quantity_rejected:
          type: number
        rejection_reason:
          type: string
          nullable: true
          enum:
          - damaged
          - wrong_item
          - expired
          - other
        notes:
          type: string
          nullable: true
        line_type:
          type: string
          enum:
          - purchase_order_item
          - stock_transfer_item
        line_id:
          type: string
          nullable: true
        variant_id:
          type: string
          nullable: true
        product_id:
          type: string
          nullable: true
        variant_name:
          type: string
          nullable: true
        variant_sku:
          type: string
          nullable: true
        thumbnail_url:
          type: string
          nullable: true
      required:
      - id
      - quantity_accepted
      - quantity_rejected
      - rejection_reason
      - notes
      - line_type
      - line_id
      - variant_id
      - product_id
      - variant_name
      - variant_sku
      - thumbnail_url
      x-typelizer: true
    StockReceipt:
      type: object
      properties:
        id:
          type: string
        number:
          type: string
        reference:
          type: string
          nullable: true
        notes:
          type: string
          nullable: true
        metadata:
          type: object
        quantity_accepted_total:
          type: number
        quantity_rejected_total:
          type: number
        received_at:
          type: string
        created_at:
          type: string
        updated_at:
          type: string
        receivable_type:
          type: string
          enum:
          - purchase_order
          - stock_transfer
        receivable_id:
          type: string
        received_by_id:
          type: string
          nullable: true
        received_by_type:
          anyOf:
          - type: string
            enum:
            - admin_user
            - api_key
          - type: string
            nullable: true
          description: The values listed are the built-in ones; extensions may add
            more.
        received_by:
          "$ref": "#/components/schemas/Actor"
        items_count:
          type: number
        items:
          type: array
          items:
            "$ref": "#/components/schemas/StockReceiptItem"
      required:
      - id
      - number
      - reference
      - notes
      - metadata
      - quantity_accepted_total
      - quantity_rejected_total
      - received_at
      - created_at
      - updated_at
      - receivable_type
      - receivable_id
      - received_by_id
      - received_by_type
      - items_count
      x-typelizer: true
    StockReservation:
      type: object
      properties:
        id:
          type: string
        stock_level_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_level_id
      - line_item_id
      - order_id
      - variant_id
      - stock_location_id
      - quantity
      - expires_at
      - active
      - created_at
      - updated_at
      x-typelizer: true
    StockTransferItem:
      type: object
      properties:
        id:
          type: string
        quantity_shipped:
          type: number
        quantity_received:
          type: number
        quantity_rejected:
          type: number
        quantity_over:
          type: number
        outstanding:
          type: number
        created_at:
          type: string
        updated_at:
          type: string
        stock_transfer_id:
          type: string
          nullable: true
        variant_id:
          type: string
          nullable: true
        product_id:
          type: string
          nullable: true
        variant_name:
          type: string
          nullable: true
        variant_sku:
          type: string
          nullable: true
        options_text:
          type: string
          nullable: true
        thumbnail_url:
          type: string
          nullable: true
      required:
      - id
      - quantity_shipped
      - quantity_received
      - quantity_rejected
      - quantity_over
      - outstanding
      - created_at
      - updated_at
      - stock_transfer_id
      - variant_id
      - product_id
      - variant_name
      - variant_sku
      - options_text
      - thumbnail_url
      x-typelizer: true
    StockTransfer:
      type: object
      properties:
        id:
          type: string
        number:
          type: string
        reference:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        source_location_id:
          type: string
        destination_location_id:
          type: string
        status:
          anyOf:
          - type: string
            enum:
            - draft
            - ready_to_ship
            - in_transit
            - partially_received
            - received
            - over_received
            - canceled
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        notes:
          type: string
          nullable: true
        metadata:
          type: object
        close_reason:
          type: string
          nullable: true
        items_count:
          type: number
        quantity_received_total:
          type: number
        quantity_rejected_total:
          type: number
        shipped_at:
          type: string
          nullable: true
        received_at:
          type: string
          nullable: true
        closed_short_at:
          type: string
          nullable: true
        deleted_at:
          type: string
          nullable: true
        closed_short:
          type: boolean
        quantity_shipped_total:
          type: number
        editable:
          type: boolean
        items:
          type: array
          items:
            "$ref": "#/components/schemas/StockTransferItem"
        stock_receipts:
          type: array
          items:
            "$ref": "#/components/schemas/StockReceipt"
        source_location:
          "$ref": "#/components/schemas/StockLocation"
        destination_location:
          "$ref": "#/components/schemas/StockLocation"
      required:
      - id
      - number
      - reference
      - created_at
      - updated_at
      - source_location_id
      - destination_location_id
      - status
      - notes
      - metadata
      - close_reason
      - items_count
      - quantity_received_total
      - quantity_rejected_total
      - shipped_at
      - received_at
      - closed_short_at
      - deleted_at
      - closed_short
      - quantity_shipped_total
      - editable
      x-typelizer: true
    StoreCreditEvent:
      type: object
      properties:
        id:
          type: string
        action:
          type: string
        authorization_code:
          type: string
          nullable: true
        display_action:
          type: string
          nullable: true
        amount:
          type: string
        created_at:
          type: string
        updated_at:
          type: string
        store_credit_id:
          type: string
        originator_type:
          type: string
          nullable: true
        originator_id:
          type: string
          nullable: true
      required:
      - id
      - action
      - authorization_code
      - display_action
      - amount
      - created_at
      - updated_at
      - store_credit_id
      - originator_type
      - originator_id
      x-typelizer: true
    StoreCredit:
      type: object
      properties:
        id:
          type: string
        amount:
          type: string
        amount_used:
          type: string
        amount_remaining:
          type: string
        currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomField"
        memo:
          type: string
          nullable: true
        metadata:
          type: object
        created_at:
          type: string
        updated_at:
          type: string
        amount_authorized:
          type: string
        outstanding:
          type: boolean
        customer_id:
          type: string
          nullable: true
        created_by_id:
          type: string
          nullable: true
        created_by_type:
          anyOf:
          - type: string
            enum:
            - admin_user
            - api_key
          - type: string
            nullable: true
          description: The values listed are the built-in ones; extensions may add
            more.
        created_by:
          "$ref": "#/components/schemas/Actor"
        originator_type:
          type: string
          nullable: true
        originator_id:
          type: string
          nullable: true
        customer:
          "$ref": "#/components/schemas/Customer"
      required:
      - id
      - amount
      - amount_used
      - amount_remaining
      - currency
      - memo
      - metadata
      - created_at
      - updated_at
      - amount_authorized
      - outstanding
      - customer_id
      - created_by_id
      - created_by_type
      - originator_type
      - originator_id
      x-typelizer: true
    Store:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        seo_title:
          type: string
          nullable: true
        meta_description:
          type: string
          nullable: true
        metadata:
          type: object
        code:
          type: string
        default_currency:
          type: string
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        default_locale:
          type: string
          enum:
          - aa
          - ab
          - ae
          - af
          - ak
          - am
          - an
          - ar
          - as
          - av
          - ay
          - az
          - ba
          - be
          - bg
          - bh
          - bi
          - bm
          - bn
          - bo
          - br
          - bs
          - ca
          - ce
          - ch
          - co
          - cr
          - cs
          - cu
          - cv
          - cy
          - da
          - de
          - de-AT
          - de-CH
          - dv
          - dz
          - ee
          - el
          - en
          - en-AU
          - en-CA
          - en-GB
          - en-IN
          - en-NZ
          - en-US
          - eo
          - es
          - es-419
          - es-CL
          - es-EC
          - es-MX
          - et
          - eu
          - fa
          - ff
          - fi
          - fj
          - fo
          - fr
          - fr-CA
          - fy
          - ga
          - gd
          - gl
          - gn
          - gu
          - gv
          - ha
          - he
          - hi
          - ho
          - hr
          - ht
          - hu
          - hy
          - hz
          - ia
          - id
          - ie
          - ig
          - ii
          - ik
          - io
          - is
          - it
          - iu
          - ja
          - jv
          - ka
          - kg
          - ki
          - kj
          - kk
          - kl
          - km
          - kn
          - ko
          - kr
          - ks
          - ku
          - kv
          - kw
          - ky
          - la
          - lb
          - lg
          - li
          - ln
          - lo
          - lt
          - lu
          - lv
          - mg
          - mh
          - mi
          - mk
          - ml
          - mn
          - mr
          - ms
          - mt
          - my
          - na
          - nb
          - nd
          - ne
          - ng
          - nl
          - nn
          - 'no'
          - nr
          - nv
          - ny
          - oc
          - oj
          - om
          - or
          - os
          - pa
          - pi
          - pl
          - ps
          - pt
          - pt-BR
          - pt-PT
          - qu
          - rm
          - rn
          - ro
          - ru
          - rw
          - sa
          - sc
          - sd
          - se
          - sg
          - si
          - sk
          - sl
          - sl-SI
          - sm
          - sn
          - so
          - sq
          - sr
          - ss
          - st
          - su
          - sv
          - sw
          - ta
          - te
          - tg
          - th
          - ti
          - tk
          - tl
          - tn
          - to
          - tr
          - ts
          - tt
          - tw
          - ty
          - ug
          - uk
          - ur
          - uz
          - ve
          - vi
          - vo
          - wa
          - wo
          - xh
          - yi
          - yo
          - za
          - zh-CN
          - zh-HK
          - zh-TW
          - zu
        default_country_code:
          type: string
          nullable: true
          enum:
          - AD
          - AE
          - AF
          - AG
          - AI
          - AL
          - AM
          - AO
          - AR
          - AS
          - AT
          - AU
          - AW
          - AZ
          - BA
          - BB
          - BD
          - BE
          - BF
          - BG
          - BH
          - BI
          - BJ
          - BL
          - BM
          - BN
          - BO
          - BQ
          - BR
          - BS
          - BT
          - BW
          - BY
          - BZ
          - CA
          - CC
          - CD
          - CF
          - CG
          - CH
          - CI
          - CK
          - CL
          - CM
          - CN
          - CO
          - CR
          - CU
          - CV
          - CW
          - CX
          - CY
          - CZ
          - DE
          - DJ
          - DK
          - DM
          - DO
          - DZ
          - EC
          - EE
          - EG
          - ER
          - ES
          - ET
          - FI
          - FJ
          - FK
          - FM
          - FO
          - FR
          - GA
          - GB
          - GD
          - GE
          - GF
          - GG
          - GH
          - GI
          - GL
          - GM
          - GN
          - GP
          - GQ
          - GR
          - GT
          - GU
          - GW
          - GY
          - HK
          - HN
          - HR
          - HT
          - HU
          - ID
          - IE
          - IL
          - IM
          - IN
          - IQ
          - IR
          - IS
          - IT
          - JE
          - JM
          - JO
          - JP
          - KE
          - KG
          - KH
          - KI
          - KM
          - KN
          - KP
          - KR
          - KW
          - KY
          - KZ
          - LA
          - LB
          - LC
          - LI
          - LK
          - LR
          - LS
          - LT
          - LU
          - LV
          - LY
          - MA
          - MC
          - MD
          - ME
          - MF
          - MG
          - MH
          - MK
          - ML
          - MM
          - MN
          - MO
          - MP
          - MQ
          - MR
          - MS
          - MT
          - MU
          - MV
          - MW
          - MX
          - MY
          - MZ
          - NA
          - NC
          - NE
          - NF
          - NG
          - NI
          - NL
          - 'NO'
          - NP
          - NR
          - NU
          - NZ
          - OM
          - PA
          - PE
          - PF
          - PG
          - PH
          - PK
          - PL
          - PM
          - PN
          - PR
          - PS
          - PT
          - PW
          - PY
          - QA
          - RE
          - RO
          - RS
          - RU
          - RW
          - SA
          - SB
          - SC
          - SD
          - SE
          - SG
          - SH
          - SI
          - SJ
          - SK
          - SL
          - SM
          - SN
          - SO
          - SR
          - SS
          - ST
          - SV
          - SX
          - SY
          - SZ
          - TC
          - TD
          - TG
          - TH
          - TJ
          - TK
          - TL
          - TM
          - TN
          - TO
          - TR
          - TT
          - TV
          - TW
          - TZ
          - UA
          - UG
          - US
          - UY
          - UZ
          - VA
          - VC
          - VE
          - VG
          - VI
          - VN
          - VU
          - WF
          - WS
          - YE
          - YT
          - ZA
          - ZM
          - ZW
        mail_from_address:
          type: string
          nullable: true
        customer_support_email:
          type: string
          nullable: true
        new_order_notifications_email:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        order_routing_strategy:
          type: string
          description: 'Order routing strategy. Built-in: rules. Extensions may register
            more.'
        payout_provider:
          type: string
          nullable: true
          description: 'Payout provider; null uses the installation default. Built-in:
            system. Provider gems register more (e.g. stripe).'
        admin_locale:
          type: string
          nullable: true
          enum:
          - aa
          - ab
          - ae
          - af
          - ak
          - am
          - an
          - ar
          - as
          - av
          - ay
          - az
          - ba
          - be
          - bg
          - bh
          - bi
          - bm
          - bn
          - bo
          - br
          - bs
          - ca
          - ce
          - ch
          - co
          - cr
          - cs
          - cu
          - cv
          - cy
          - da
          - de
          - de-AT
          - de-CH
          - dv
          - dz
          - ee
          - el
          - en
          - en-AU
          - en-CA
          - en-GB
          - en-IN
          - en-NZ
          - en-US
          - eo
          - es
          - es-419
          - es-CL
          - es-EC
          - es-MX
          - et
          - eu
          - fa
          - ff
          - fi
          - fj
          - fo
          - fr
          - fr-CA
          - fy
          - ga
          - gd
          - gl
          - gn
          - gu
          - gv
          - ha
          - he
          - hi
          - ho
          - hr
          - ht
          - hu
          - hy
          - hz
          - ia
          - id
          - ie
          - ig
          - ii
          - ik
          - io
          - is
          - it
          - iu
          - ja
          - jv
          - ka
          - kg
          - ki
          - kj
          - kk
          - kl
          - km
          - kn
          - ko
          - kr
          - ks
          - ku
          - kv
          - kw
          - ky
          - la
          - lb
          - lg
          - li
          - ln
          - lo
          - lt
          - lu
          - lv
          - mg
          - mh
          - mi
          - mk
          - ml
          - mn
          - mr
          - ms
          - mt
          - my
          - na
          - nb
          - nd
          - ne
          - ng
          - nl
          - nn
          - 'no'
          - nr
          - nv
          - ny
          - oc
          - oj
          - om
          - or
          - os
          - pa
          - pi
          - pl
          - ps
          - pt
          - pt-BR
          - pt-PT
          - qu
          - rm
          - rn
          - ro
          - ru
          - rw
          - sa
          - sc
          - sd
          - se
          - sg
          - si
          - sk
          - sl
          - sl-SI
          - sm
          - sn
          - so
          - sq
          - sr
          - ss
          - st
          - su
          - sv
          - sw
          - ta
          - te
          - tg
          - th
          - ti
          - tk
          - tl
          - tn
          - to
          - tr
          - ts
          - tt
          - tw
          - ty
          - ug
          - uk
          - ur
          - uz
          - ve
          - vi
          - vo
          - wa
          - wo
          - xh
          - yi
          - yo
          - za
          - zh-CN
          - zh-HK
          - zh-TW
          - zu
        timezone:
          anyOf:
          - type: string
            enum:
            - Africa/Algiers
            - Africa/Cairo
            - Africa/Casablanca
            - Africa/Harare
            - Africa/Johannesburg
            - Africa/Monrovia
            - Africa/Nairobi
            - America/Argentina/Buenos_Aires
            - America/Asuncion
            - America/Bogota
            - America/Caracas
            - America/Chicago
            - America/Chihuahua
            - America/Denver
            - America/Guatemala
            - America/Guyana
            - America/Halifax
            - America/Indiana/Indianapolis
            - America/Juneau
            - America/La_Paz
            - America/Lima
            - America/Los_Angeles
            - America/Mazatlan
            - America/Mexico_City
            - America/Monterrey
            - America/Montevideo
            - America/New_York
            - America/Nuuk
            - America/Phoenix
            - America/Puerto_Rico
            - America/Regina
            - America/Santiago
            - America/Sao_Paulo
            - America/St_Johns
            - America/Tijuana
            - Asia/Almaty
            - Asia/Baghdad
            - Asia/Baku
            - Asia/Bangkok
            - Asia/Chongqing
            - Asia/Colombo
            - Asia/Dhaka
            - Asia/Hong_Kong
            - Asia/Irkutsk
            - Asia/Jakarta
            - Asia/Jerusalem
            - Asia/Kabul
            - Asia/Kamchatka
            - Asia/Karachi
            - Asia/Kathmandu
            - Asia/Kolkata
            - Asia/Krasnoyarsk
            - Asia/Kuala_Lumpur
            - Asia/Kuwait
            - Asia/Magadan
            - Asia/Muscat
            - Asia/Novosibirsk
            - Asia/Riyadh
            - Asia/Seoul
            - Asia/Shanghai
            - Asia/Singapore
            - Asia/Srednekolymsk
            - Asia/Taipei
            - Asia/Tashkent
            - Asia/Tbilisi
            - Asia/Tehran
            - Asia/Tokyo
            - Asia/Ulaanbaatar
            - Asia/Urumqi
            - Asia/Vladivostok
            - Asia/Yakutsk
            - Asia/Yangon
            - Asia/Yekaterinburg
            - Asia/Yerevan
            - Atlantic/Azores
            - Atlantic/Cape_Verde
            - Atlantic/South_Georgia
            - Australia/Adelaide
            - Australia/Brisbane
            - Australia/Canberra
            - Australia/Darwin
            - Australia/Hobart
            - Australia/Melbourne
            - Australia/Perth
            - Australia/Sydney
            - Etc/GMT+12
            - Europe/Amsterdam
            - Europe/Athens
            - Europe/Belgrade
            - Europe/Berlin
            - Europe/Bratislava
            - Europe/Brussels
            - Europe/Bucharest
            - Europe/Budapest
            - Europe/Copenhagen
            - Europe/Dublin
            - Europe/Helsinki
            - Europe/Istanbul
            - Europe/Kaliningrad
            - Europe/Kyiv
            - Europe/Lisbon
            - Europe/Ljubljana
            - Europe/London
            - Europe/Madrid
            - Europe/Minsk
            - Europe/Moscow
            - Europe/Paris
            - Europe/Prague
            - Europe/Riga
            - Europe/Rome
            - Europe/Samara
            - Europe/Sarajevo
            - Europe/Skopje
            - Europe/Sofia
            - Europe/Stockholm
            - Europe/Tallinn
            - Europe/Vienna
            - Europe/Vilnius
            - Europe/Volgograd
            - Europe/Warsaw
            - Europe/Zagreb
            - Europe/Zurich
            - Pacific/Apia
            - Pacific/Auckland
            - Pacific/Chatham
            - Pacific/Fakaofo
            - Pacific/Fiji
            - Pacific/Guadalcanal
            - Pacific/Guam
            - Pacific/Honolulu
            - Pacific/Majuro
            - Pacific/Midway
            - Pacific/Noumea
            - Pacific/Pago_Pago
            - Pacific/Port_Moresby
            - Pacific/Tongatapu
            - UTC
          - type: string
          description: Common IANA time zones; any other IANA time zone identifier
            is accepted too.
        storefront_url:
          type: string
          nullable: true
        weight_unit:
          type: string
          enum:
          - g
          - kg
          - lb
          - oz
        unit_system:
          type: string
          enum:
          - metric
          - imperial
        storefront_access:
          type: string
          enum:
          - public
          - prices_hidden
          - login_required
        guest_checkout:
          type: boolean
        always_include_confirm_step:
          type: boolean
        company_field_enabled:
          type: boolean
        address_requires_company:
          type: boolean
        address_requires_phone:
          type: boolean
        capture_method:
          type: string
          enum:
          - checkout
          - on_dispatch
          - manual
        track_inventory_levels:
          type: boolean
        stock_reservations_enabled:
          type: boolean
        low_stock_threshold:
          type: number
        tax_using_ship_address:
          type: boolean
        track_price_history:
          type: boolean
        show_products_without_price:
          type: boolean
        disable_sku_validation:
          type: boolean
        pricing_provider:
          type: string
        inventory_provider:
          type: string
        pricing_provider_failure_policy:
          type: string
          enum:
          - fallback
          - strict
        inventory_provider_failure_policy:
          type: string
          enum:
          - fallback
          - strict
        default_payouts_schedule_interval:
          type: string
          enum:
          - daily
          - weekly
          - biweekly
          - monthly
          - manual
        auto_approve_sellers:
          type: boolean
        auto_approve_seller_products:
          type: boolean
        seller_digital_assets_enabled:
          type: boolean
        seller_digital_asset_content_types:
          type: array
          items:
            type: string
        review_seller_digital_asset_changes:
          type: boolean
        send_seller_transactional_emails:
          type: boolean
        document_number_format:
          type: string
          enum:
          - sequential
          - random
        order_number_prefix:
          type: string
        order_number_suffix:
          type: string
        order_number_sequence_start:
          type: number
        limit_digital_download_count:
          type: boolean
        digital_asset_authorized_clicks:
          type: number
        limit_digital_download_days:
          type: boolean
        digital_asset_authorized_days:
          type: number
        send_consumer_transactional_emails:
          type: boolean
        email_accent_color:
          type: string
          nullable: true
        email_background_color:
          type: string
          nullable: true
        email_card_color:
          type: string
          nullable: true
        email_text_color:
          type: string
          nullable: true
        email_heading_color:
          type: string
          nullable: true
        email_font:
          type: string
          nullable: true
          enum:
          - inter
          - system
          - helvetica
          - georgia
          - roboto
          - lato
          - merriweather
        order_number_sequence_started:
          type: boolean
        default_minimum_payout_amount:
          type: string
          nullable: true
        default_commission_tax_rate:
          type: string
          nullable: true
        url:
          type: string
        api_url:
          type: string
        setup_tasks:
          type: array
          items:
            "$ref": "#/components/schemas/SetupTask"
        supported_currencies:
          type: array
          items:
            type: string
            enum:
            - AED
            - AFN
            - ALL
            - AMD
            - ANG
            - AOA
            - ARS
            - AUD
            - AWG
            - AZN
            - BAM
            - BBD
            - BDT
            - BGN
            - BHD
            - BIF
            - BMD
            - BND
            - BOB
            - BRL
            - BSD
            - BTN
            - BWP
            - BYN
            - BYR
            - BZD
            - CAD
            - CDF
            - CHF
            - CLF
            - CLP
            - CNY
            - COP
            - CRC
            - CUC
            - CUP
            - CVE
            - CZK
            - DJF
            - DKK
            - DOP
            - DZD
            - EEK
            - EGP
            - ERN
            - ETB
            - EUR
            - FJD
            - FKP
            - GBP
            - GEL
            - GHS
            - GIP
            - GMD
            - GNF
            - GTQ
            - GYD
            - HKD
            - HNL
            - HRK
            - HTG
            - HUF
            - IDR
            - ILS
            - INR
            - IQD
            - IRR
            - ISK
            - JMD
            - JOD
            - JPY
            - KES
            - KGS
            - KHR
            - KMF
            - KPW
            - KRW
            - KWD
            - KYD
            - KZT
            - LAK
            - LBP
            - LKR
            - LRD
            - LSL
            - LTL
            - LVL
            - LYD
            - MAD
            - MDL
            - MGA
            - MKD
            - MMK
            - MNT
            - MOP
            - MRO
            - MRU
            - MTL
            - MUR
            - MVR
            - MWK
            - MXN
            - MYR
            - MZN
            - NAD
            - NGN
            - NIO
            - NOK
            - NPR
            - NZD
            - OMR
            - PAB
            - PEN
            - PGK
            - PHP
            - PKR
            - PLN
            - PYG
            - QAR
            - RON
            - RSD
            - RUB
            - RWF
            - SAR
            - SBD
            - SCR
            - SDG
            - SEK
            - SGD
            - SHP
            - SKK
            - SLE
            - SLL
            - SOS
            - SRD
            - SSP
            - STD
            - STN
            - SVC
            - SYP
            - SZL
            - THB
            - TJS
            - TMM
            - TMT
            - TND
            - TOP
            - TRY
            - TTD
            - TWD
            - TZS
            - UAH
            - UGX
            - USD
            - UYI
            - UYU
            - UYW
            - UZS
            - VED
            - VEF
            - VES
            - VND
            - VUV
            - WST
            - XAF
            - XCD
            - XCG
            - XOF
            - XPF
            - YER
            - ZAR
            - ZMK
            - ZMW
            - ZWD
            - ZWG
            - ZWL
            - ZWN
            - ZWR
        supported_locales:
          type: array
          items:
            type: string
            enum:
            - aa
            - ab
            - ae
            - af
            - ak
            - am
            - an
            - ar
            - as
            - av
            - ay
            - az
            - ba
            - be
            - bg
            - bh
            - bi
            - bm
            - bn
            - bo
            - br
            - bs
            - ca
            - ce
            - ch
            - co
            - cr
            - cs
            - cu
            - cv
            - cy
            - da
            - de
            - de-AT
            - de-CH
            - dv
            - dz
            - ee
            - el
            - en
            - en-AU
            - en-CA
            - en-GB
            - en-IN
            - en-NZ
            - en-US
            - eo
            - es
            - es-419
            - es-CL
            - es-EC
            - es-MX
            - et
            - eu
            - fa
            - ff
            - fi
            - fj
            - fo
            - fr
            - fr-CA
            - fy
            - ga
            - gd
            - gl
            - gn
            - gu
            - gv
            - ha
            - he
            - hi
            - ho
            - hr
            - ht
            - hu
            - hy
            - hz
            - ia
            - id
            - ie
            - ig
            - ii
            - ik
            - io
            - is
            - it
            - iu
            - ja
            - jv
            - ka
            - kg
            - ki
            - kj
            - kk
            - kl
            - km
            - kn
            - ko
            - kr
            - ks
            - ku
            - kv
            - kw
            - ky
            - la
            - lb
            - lg
            - li
            - ln
            - lo
            - lt
            - lu
            - lv
            - mg
            - mh
            - mi
            - mk
            - ml
            - mn
            - mr
            - ms
            - mt
            - my
            - na
            - nb
            - nd
            - ne
            - ng
            - nl
            - nn
            - 'no'
            - nr
            - nv
            - ny
            - oc
            - oj
            - om
            - or
            - os
            - pa
            - pi
            - pl
            - ps
            - pt
            - pt-BR
            - pt-PT
            - qu
            - rm
            - rn
            - ro
            - ru
            - rw
            - sa
            - sc
            - sd
            - se
            - sg
            - si
            - sk
            - sl
            - sl-SI
            - sm
            - sn
            - so
            - sq
            - sr
            - ss
            - st
            - su
            - sv
            - sw
            - ta
            - te
            - tg
            - th
            - ti
            - tk
            - tl
            - tn
            - to
            - tr
            - ts
            - tt
            - tw
            - ty
            - ug
            - uk
            - ur
            - uz
            - ve
            - vi
            - vo
            - wa
            - wo
            - xh
            - yi
            - yo
            - za
            - zh-CN
            - zh-HK
            - zh-TW
            - zu
        available_locales:
          type: array
          items:
            type: string
            enum:
            - aa
            - ab
            - ae
            - af
            - ak
            - am
            - an
            - ar
            - as
            - av
            - ay
            - az
            - ba
            - be
            - bg
            - bh
            - bi
            - bm
            - bn
            - bo
            - br
            - bs
            - ca
            - ce
            - ch
            - co
            - cr
            - cs
            - cu
            - cv
            - cy
            - da
            - de
            - de-AT
            - de-CH
            - dv
            - dz
            - ee
            - el
            - en
            - en-AU
            - en-CA
            - en-GB
            - en-IN
            - en-NZ
            - en-US
            - eo
            - es
            - es-419
            - es-CL
            - es-EC
            - es-MX
            - et
            - eu
            - fa
            - ff
            - fi
            - fj
            - fo
            - fr
            - fr-CA
            - fy
            - ga
            - gd
            - gl
            - gn
            - gu
            - gv
            - ha
            - he
            - hi
            - ho
            - hr
            - ht
            - hu
            - hy
            - hz
            - ia
            - id
            - ie
            - ig
            - ii
            - ik
            - io
            - is
            - it
            - iu
            - ja
            - jv
            - ka
            - kg
            - ki
            - kj
            - kk
            - kl
            - km
            - kn
            - ko
            - kr
            - ks
            - ku
            - kv
            - kw
            - ky
            - la
            - lb
            - lg
            - li
            - ln
            - lo
            - lt
            - lu
            - lv
            - mg
            - mh
            - mi
            - mk
            - ml
            - mn
            - mr
            - ms
            - mt
            - my
            - na
            - nb
            - nd
            - ne
            - ng
            - nl
            - nn
            - 'no'
            - nr
            - nv
            - ny
            - oc
            - oj
            - om
            - or
            - os
            - pa
            - pi
            - pl
            - ps
            - pt
            - pt-BR
            - pt-PT
            - qu
            - rm
            - rn
            - ro
            - ru
            - rw
            - sa
            - sc
            - sd
            - se
            - sg
            - si
            - sk
            - sl
            - sl-SI
            - sm
            - sn
            - so
            - sq
            - sr
            - ss
            - st
            - su
            - sv
            - sw
            - ta
            - te
            - tg
            - th
            - ti
            - tk
            - tl
            - tn
            - to
            - tr
            - ts
            - tt
            - tw
            - ty
            - ug
            - uk
            - ur
            - uz
            - ve
            - vi
            - vo
            - wa
            - wo
            - xh
            - yi
            - yo
            - za
            - zh-CN
            - zh-HK
            - zh-TW
            - zu
        logo_url:
          type: string
          nullable: true
        mailer_logo_url:
          type: string
          nullable: true
      required:
      - id
      - name
      - seo_title
      - meta_description
      - metadata
      - code
      - default_currency
      - default_locale
      - default_country_code
      - mail_from_address
      - customer_support_email
      - new_order_notifications_email
      - created_at
      - updated_at
      - order_routing_strategy
      - payout_provider
      - admin_locale
      - timezone
      - storefront_url
      - weight_unit
      - unit_system
      - storefront_access
      - guest_checkout
      - always_include_confirm_step
      - company_field_enabled
      - address_requires_company
      - address_requires_phone
      - capture_method
      - track_inventory_levels
      - stock_reservations_enabled
      - low_stock_threshold
      - tax_using_ship_address
      - track_price_history
      - show_products_without_price
      - disable_sku_validation
      - pricing_provider
      - inventory_provider
      - pricing_provider_failure_policy
      - inventory_provider_failure_policy
      - default_payouts_schedule_interval
      - auto_approve_sellers
      - auto_approve_seller_products
      - seller_digital_assets_enabled
      - seller_digital_asset_content_types
      - review_seller_digital_asset_changes
      - send_seller_transactional_emails
      - document_number_format
      - order_number_prefix
      - order_number_suffix
      - order_number_sequence_start
      - limit_digital_download_count
      - digital_asset_authorized_clicks
      - limit_digital_download_days
      - digital_asset_authorized_days
      - send_consumer_transactional_emails
      - email_accent_color
      - email_background_color
      - email_card_color
      - email_text_color
      - email_heading_color
      - email_font
      - order_number_sequence_started
      - default_minimum_payout_amount
      - default_commission_tax_rate
      - url
      - api_url
      - setup_tasks
      - supported_currencies
      - supported_locales
      - available_locales
      - logo_url
      - mailer_logo_url
      x-typelizer: true
    Supplier:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        contact_name:
          type: string
          nullable: true
        email:
          type: string
          nullable: true
        phone:
          type: string
          nullable: true
        notes:
          type: string
          nullable: true
        address1:
          type: string
          nullable: true
        address2:
          type: string
          nullable: true
        city:
          type: string
          nullable: true
        state_name:
          type: string
          nullable: true
        state_code:
          type: string
          nullable: true
        country_code:
          type: string
          nullable: true
          enum:
          - AD
          - AE
          - AF
          - AG
          - AI
          - AL
          - AM
          - AO
          - AR
          - AS
          - AT
          - AU
          - AW
          - AZ
          - BA
          - BB
          - BD
          - BE
          - BF
          - BG
          - BH
          - BI
          - BJ
          - BL
          - BM
          - BN
          - BO
          - BQ
          - BR
          - BS
          - BT
          - BW
          - BY
          - BZ
          - CA
          - CC
          - CD
          - CF
          - CG
          - CH
          - CI
          - CK
          - CL
          - CM
          - CN
          - CO
          - CR
          - CU
          - CV
          - CW
          - CX
          - CY
          - CZ
          - DE
          - DJ
          - DK
          - DM
          - DO
          - DZ
          - EC
          - EE
          - EG
          - ER
          - ES
          - ET
          - FI
          - FJ
          - FK
          - FM
          - FO
          - FR
          - GA
          - GB
          - GD
          - GE
          - GF
          - GG
          - GH
          - GI
          - GL
          - GM
          - GN
          - GP
          - GQ
          - GR
          - GT
          - GU
          - GW
          - GY
          - HK
          - HN
          - HR
          - HT
          - HU
          - ID
          - IE
          - IL
          - IM
          - IN
          - IQ
          - IR
          - IS
          - IT
          - JE
          - JM
          - JO
          - JP
          - KE
          - KG
          - KH
          - KI
          - KM
          - KN
          - KP
          - KR
          - KW
          - KY
          - KZ
          - LA
          - LB
          - LC
          - LI
          - LK
          - LR
          - LS
          - LT
          - LU
          - LV
          - LY
          - MA
          - MC
          - MD
          - ME
          - MF
          - MG
          - MH
          - MK
          - ML
          - MM
          - MN
          - MO
          - MP
          - MQ
          - MR
          - MS
          - MT
          - MU
          - MV
          - MW
          - MX
          - MY
          - MZ
          - NA
          - NC
          - NE
          - NF
          - NG
          - NI
          - NL
          - 'NO'
          - NP
          - NR
          - NU
          - NZ
          - OM
          - PA
          - PE
          - PF
          - PG
          - PH
          - PK
          - PL
          - PM
          - PN
          - PR
          - PS
          - PT
          - PW
          - PY
          - QA
          - RE
          - RO
          - RS
          - RU
          - RW
          - SA
          - SB
          - SC
          - SD
          - SE
          - SG
          - SH
          - SI
          - SJ
          - SK
          - SL
          - SM
          - SN
          - SO
          - SR
          - SS
          - ST
          - SV
          - SX
          - SY
          - SZ
          - TC
          - TD
          - TG
          - TH
          - TJ
          - TK
          - TL
          - TM
          - TN
          - TO
          - TR
          - TT
          - TV
          - TW
          - TZ
          - UA
          - UG
          - US
          - UY
          - UZ
          - VA
          - VC
          - VE
          - VG
          - VI
          - VN
          - VU
          - WF
          - WS
          - YE
          - YT
          - ZA
          - ZM
          - ZW
        postal_code:
          type: string
          nullable: true
        purchase_orders_count:
          type: number
        metadata:
          type: object
        created_at:
          type: string
        updated_at:
          type: string
        deleted_at:
          type: string
          nullable: true
        can_be_deleted:
          type: boolean
      required:
      - id
      - name
      - contact_name
      - email
      - phone
      - notes
      - address1
      - address2
      - city
      - state_name
      - state_code
      - country_code
      - postal_code
      - purchase_orders_count
      - metadata
      - created_at
      - updated_at
      - deleted_at
      - can_be_deleted
      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
    TaxExemptionCertificate:
      type: object
      properties:
        id:
          type: string
        certificate_number:
          type: string
        status:
          anyOf:
          - type: string
            enum:
            - pending
            - verified
            - expired
            - revoked
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        issuing_authority:
          type: string
          nullable: true
        metadata:
          type: object
          nullable: true
        issued_at:
          type: string
          nullable: true
        expires_at:
          type: string
          nullable: true
        verified_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        company_id:
          type: string
        tax_exemption_reason_id:
          type: string
        tax_exemption_reason:
          "$ref": "#/components/schemas/TaxExemptionReason"
        country_code:
          type: string
          nullable: true
          enum:
          - AD
          - AE
          - AF
          - AG
          - AI
          - AL
          - AM
          - AO
          - AR
          - AS
          - AT
          - AU
          - AW
          - AZ
          - BA
          - BB
          - BD
          - BE
          - BF
          - BG
          - BH
          - BI
          - BJ
          - BL
          - BM
          - BN
          - BO
          - BQ
          - BR
          - BS
          - BT
          - BW
          - BY
          - BZ
          - CA
          - CC
          - CD
          - CF
          - CG
          - CH
          - CI
          - CK
          - CL
          - CM
          - CN
          - CO
          - CR
          - CU
          - CV
          - CW
          - CX
          - CY
          - CZ
          - DE
          - DJ
          - DK
          - DM
          - DO
          - DZ
          - EC
          - EE
          - EG
          - ER
          - ES
          - ET
          - FI
          - FJ
          - FK
          - FM
          - FO
          - FR
          - GA
          - GB
          - GD
          - GE
          - GF
          - GG
          - GH
          - GI
          - GL
          - GM
          - GN
          - GP
          - GQ
          - GR
          - GT
          - GU
          - GW
          - GY
          - HK
          - HN
          - HR
          - HT
          - HU
          - ID
          - IE
          - IL
          - IM
          - IN
          - IQ
          - IR
          - IS
          - IT
          - JE
          - JM
          - JO
          - JP
          - KE
          - KG
          - KH
          - KI
          - KM
          - KN
          - KP
          - KR
          - KW
          - KY
          - KZ
          - LA
          - LB
          - LC
          - LI
          - LK
          - LR
          - LS
          - LT
          - LU
          - LV
          - LY
          - MA
          - MC
          - MD
          - ME
          - MF
          - MG
          - MH
          - MK
          - ML
          - MM
          - MN
          - MO
          - MP
          - MQ
          - MR
          - MS
          - MT
          - MU
          - MV
          - MW
          - MX
          - MY
          - MZ
          - NA
          - NC
          - NE
          - NF
          - NG
          - NI
          - NL
          - 'NO'
          - NP
          - NR
          - NU
          - NZ
          - OM
          - PA
          - PE
          - PF
          - PG
          - PH
          - PK
          - PL
          - PM
          - PN
          - PR
          - PS
          - PT
          - PW
          - PY
          - QA
          - RE
          - RO
          - RS
          - RU
          - RW
          - SA
          - SB
          - SC
          - SD
          - SE
          - SG
          - SH
          - SI
          - SJ
          - SK
          - SL
          - SM
          - SN
          - SO
          - SR
          - SS
          - ST
          - SV
          - SX
          - SY
          - SZ
          - TC
          - TD
          - TG
          - TH
          - TJ
          - TK
          - TL
          - TM
          - TN
          - TO
          - TR
          - TT
          - TV
          - TW
          - TZ
          - UA
          - UG
          - US
          - UY
          - UZ
          - VA
          - VC
          - VE
          - VG
          - VI
          - VN
          - VU
          - WF
          - WS
          - YE
          - YT
          - ZA
          - ZM
          - ZW
        state_code:
          type: string
          nullable: true
        active:
          type: boolean
        lapsed:
          type: boolean
        can_be_deleted:
          type: boolean
        document_filename:
          type: string
          nullable: true
        document_byte_size:
          type: number
          nullable: true
        document_url:
          type: string
          nullable: true
      required:
      - id
      - certificate_number
      - status
      - issuing_authority
      - metadata
      - issued_at
      - expires_at
      - verified_at
      - created_at
      - updated_at
      - company_id
      - tax_exemption_reason_id
      - country_code
      - state_code
      - active
      - lapsed
      - can_be_deleted
      - document_filename
      - document_byte_size
      - document_url
      x-typelizer: true
    TaxExemptionReason:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        code:
          type: string
        active:
          type: boolean
        metadata:
          type: object
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        can_be_deleted:
          type: boolean
      required:
      - id
      - name
      - code
      - active
      - metadata
      - created_at
      - updated_at
      - can_be_deleted
      x-typelizer: true
    TaxIdentifier:
      type: object
      properties:
        id:
          type: string
        kind:
          type: string
          description: 'Tax identifier kind, keyed to a registered validator. Built-in:
            eu_vat. Extensions may register more.'
        value:
          type: string
        validation_status:
          type: string
          nullable: true
          enum:
          - pending
          - verified
          - unverified
          - unavailable
          - unsupported
        validation_evidence:
          type: object
          nullable: true
        source:
          type: string
          nullable: true
          enum:
          - override
          - company
          - customer
        validated_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        validatable:
          type: boolean
        customer_id:
          type: string
          nullable: true
        cart_id:
          type: string
          nullable: true
        order_id:
          type: string
          nullable: true
      required:
      - id
      - kind
      - value
      - validation_status
      - validation_evidence
      - source
      - validated_at
      - created_at
      - updated_at
      - validatable
      - customer_id
      - cart_id
      - order_id
      x-typelizer: true
    TaxLine:
      type: object
      properties:
        id:
          type: string
        label:
          type: string
        included:
          type: boolean
        credit:
          type: boolean
        rate:
          type: string
          nullable: true
        tax_rate_id:
          type: string
          nullable: true
        line_item_id:
          type: string
          nullable: true
        fulfillment_id:
          type: string
          nullable: true
        fee_id:
          type: string
          nullable: true
        return_line_item_id:
          type: string
          nullable: true
        claim_line_item_id:
          type: string
          nullable: true
        exchange_line_item_id:
          type: string
          nullable: true
        amount:
          type: string
        provider_id:
          type: string
          nullable: true
        metadata:
          type: object
          nullable: true
        taxability_reason:
          anyOf:
          - type: string
            enum:
            - standard_rated
            - reduced_rated
            - zero_rated
            - reverse_charge
            - intra_community_supply
            - export
            - customer_exempt
            - product_exempt
            - not_collecting
            - not_subject_to_tax
          - type: string
            nullable: true
          description: The values listed are the built-in ones; extensions may add
            more.
        country_code:
          type: string
          nullable: true
          enum:
          - AD
          - AE
          - AF
          - AG
          - AI
          - AL
          - AM
          - AO
          - AR
          - AS
          - AT
          - AU
          - AW
          - AZ
          - BA
          - BB
          - BD
          - BE
          - BF
          - BG
          - BH
          - BI
          - BJ
          - BL
          - BM
          - BN
          - BO
          - BQ
          - BR
          - BS
          - BT
          - BW
          - BY
          - BZ
          - CA
          - CC
          - CD
          - CF
          - CG
          - CH
          - CI
          - CK
          - CL
          - CM
          - CN
          - CO
          - CR
          - CU
          - CV
          - CW
          - CX
          - CY
          - CZ
          - DE
          - DJ
          - DK
          - DM
          - DO
          - DZ
          - EC
          - EE
          - EG
          - ER
          - ES
          - ET
          - FI
          - FJ
          - FK
          - FM
          - FO
          - FR
          - GA
          - GB
          - GD
          - GE
          - GF
          - GG
          - GH
          - GI
          - GL
          - GM
          - GN
          - GP
          - GQ
          - GR
          - GT
          - GU
          - GW
          - GY
          - HK
          - HN
          - HR
          - HT
          - HU
          - ID
          - IE
          - IL
          - IM
          - IN
          - IQ
          - IR
          - IS
          - IT
          - JE
          - JM
          - JO
          - JP
          - KE
          - KG
          - KH
          - KI
          - KM
          - KN
          - KP
          - KR
          - KW
          - KY
          - KZ
          - LA
          - LB
          - LC
          - LI
          - LK
          - LR
          - LS
          - LT
          - LU
          - LV
          - LY
          - MA
          - MC
          - MD
          - ME
          - MF
          - MG
          - MH
          - MK
          - ML
          - MM
          - MN
          - MO
          - MP
          - MQ
          - MR
          - MS
          - MT
          - MU
          - MV
          - MW
          - MX
          - MY
          - MZ
          - NA
          - NC
          - NE
          - NF
          - NG
          - NI
          - NL
          - 'NO'
          - NP
          - NR
          - NU
          - NZ
          - OM
          - PA
          - PE
          - PF
          - PG
          - PH
          - PK
          - PL
          - PM
          - PN
          - PR
          - PS
          - PT
          - PW
          - PY
          - QA
          - RE
          - RO
          - RS
          - RU
          - RW
          - SA
          - SB
          - SC
          - SD
          - SE
          - SG
          - SH
          - SI
          - SJ
          - SK
          - SL
          - SM
          - SN
          - SO
          - SR
          - SS
          - ST
          - SV
          - SX
          - SY
          - SZ
          - TC
          - TD
          - TG
          - TH
          - TJ
          - TK
          - TL
          - TM
          - TN
          - TO
          - TR
          - TT
          - TV
          - TW
          - TZ
          - UA
          - UG
          - US
          - UY
          - UZ
          - VA
          - VC
          - VE
          - VG
          - VI
          - VN
          - VU
          - WF
          - WS
          - YE
          - YT
          - ZA
          - ZM
          - ZW
        state_code:
          type: string
          nullable: true
        data:
          type: object
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        original_tax_line_id:
          type: string
          nullable: true
      required:
      - id
      - label
      - included
      - credit
      - rate
      - tax_rate_id
      - line_item_id
      - fulfillment_id
      - fee_id
      - return_line_item_id
      - claim_line_item_id
      - exchange_line_item_id
      - amount
      - provider_id
      - metadata
      - taxability_reason
      - country_code
      - state_code
      - data
      - created_at
      - updated_at
      - original_tax_line_id
      x-typelizer: true
    TaxRate:
      type: object
      properties:
        id:
          type: string
        name:
          type: string
        show_rate_in_label:
          type: boolean
        metadata:
          type: object
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        deleted_at:
          type: string
          nullable: true
        rate:
          type: string
          nullable: true
        rate_percent:
          type: string
          nullable: true
        tax_category_id:
          type: string
          nullable: true
        store_id:
          type: string
          nullable: true
        country_code:
          type: string
          nullable: true
          enum:
          - AD
          - AE
          - AF
          - AG
          - AI
          - AL
          - AM
          - AO
          - AR
          - AS
          - AT
          - AU
          - AW
          - AZ
          - BA
          - BB
          - BD
          - BE
          - BF
          - BG
          - BH
          - BI
          - BJ
          - BL
          - BM
          - BN
          - BO
          - BQ
          - BR
          - BS
          - BT
          - BW
          - BY
          - BZ
          - CA
          - CC
          - CD
          - CF
          - CG
          - CH
          - CI
          - CK
          - CL
          - CM
          - CN
          - CO
          - CR
          - CU
          - CV
          - CW
          - CX
          - CY
          - CZ
          - DE
          - DJ
          - DK
          - DM
          - DO
          - DZ
          - EC
          - EE
          - EG
          - ER
          - ES
          - ET
          - FI
          - FJ
          - FK
          - FM
          - FO
          - FR
          - GA
          - GB
          - GD
          - GE
          - GF
          - GG
          - GH
          - GI
          - GL
          - GM
          - GN
          - GP
          - GQ
          - GR
          - GT
          - GU
          - GW
          - GY
          - HK
          - HN
          - HR
          - HT
          - HU
          - ID
          - IE
          - IL
          - IM
          - IN
          - IQ
          - IR
          - IS
          - IT
          - JE
          - JM
          - JO
          - JP
          - KE
          - KG
          - KH
          - KI
          - KM
          - KN
          - KP
          - KR
          - KW
          - KY
          - KZ
          - LA
          - LB
          - LC
          - LI
          - LK
          - LR
          - LS
          - LT
          - LU
          - LV
          - LY
          - MA
          - MC
          - MD
          - ME
          - MF
          - MG
          - MH
          - MK
          - ML
          - MM
          - MN
          - MO
          - MP
          - MQ
          - MR
          - MS
          - MT
          - MU
          - MV
          - MW
          - MX
          - MY
          - MZ
          - NA
          - NC
          - NE
          - NF
          - NG
          - NI
          - NL
          - 'NO'
          - NP
          - NR
          - NU
          - NZ
          - OM
          - PA
          - PE
          - PF
          - PG
          - PH
          - PK
          - PL
          - PM
          - PN
          - PR
          - PS
          - PT
          - PW
          - PY
          - QA
          - RE
          - RO
          - RS
          - RU
          - RW
          - SA
          - SB
          - SC
          - SD
          - SE
          - SG
          - SH
          - SI
          - SJ
          - SK
          - SL
          - SM
          - SN
          - SO
          - SR
          - SS
          - ST
          - SV
          - SX
          - SY
          - SZ
          - TC
          - TD
          - TG
          - TH
          - TJ
          - TK
          - TL
          - TM
          - TN
          - TO
          - TR
          - TT
          - TV
          - TW
          - TZ
          - UA
          - UG
          - US
          - UY
          - UZ
          - VA
          - VC
          - VE
          - VG
          - VI
          - VN
          - VU
          - WF
          - WS
          - YE
          - YT
          - ZA
          - ZM
          - ZW
        state_code:
          type: string
          nullable: true
      required:
      - id
      - name
      - show_rate_in_label
      - metadata
      - created_at
      - updated_at
      - deleted_at
      - rate
      - rate_percent
      - tax_category_id
      - store_id
      - country_code
      - state_code
      x-typelizer: true
    UpdateStatus:
      type: object
      properties:
        current_version:
          type: string
        enabled:
          type: boolean
        checked_at:
          type: string
          nullable: true
        update_available:
          type: boolean
        latest_version:
          type: string
          nullable: true
        latest_release_url:
          type: string
          nullable: true
        latest_release_published_at:
          type: string
          nullable: true
      required:
      - current_version
      - enabled
      - checked_at
      - update_available
      - latest_version
      - latest_release_url
      - latest_release_published_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
        preorder_ships_at:
          type: string
          nullable: true
        thumbnail_url:
          type: string
          nullable: true
        purchasable:
          type: boolean
        in_stock:
          type: boolean
        backorderable:
          type: boolean
        preorder:
          type: boolean
        weight:
          type: number
          nullable: true
        height:
          type: number
          nullable: true
        width:
          type: number
          nullable: true
        depth:
          type: number
          nullable: true
        weight_unit:
          type: string
          enum:
          - g
          - kg
          - lb
          - oz
        dimensions_unit:
          type: string
          enum:
          - mm
          - cm
          - in
          - ft
        minimum_order_quantity:
          type: number
          nullable: true
        order_multiple:
          type: number
          nullable: true
        purchase_unit:
          type: string
          nullable: true
          enum:
          - unit
          - carton
        units_per_carton:
          type: number
          nullable: true
        price:
          "$ref": "#/components/schemas/Price"
        original_price:
          allOf:
          - "$ref": "#/components/schemas/Price"
          nullable: true
        seller_id:
          type: string
          nullable: true
        seller:
          "$ref": "#/components/schemas/Seller"
        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
        external_references:
          type: object
        metadata:
          type: object
        position:
          type: number
        cost_currency:
          type: string
          nullable: true
          enum:
          - AED
          - AFN
          - ALL
          - AMD
          - ANG
          - AOA
          - ARS
          - AUD
          - AWG
          - AZN
          - BAM
          - BBD
          - BDT
          - BGN
          - BHD
          - BIF
          - BMD
          - BND
          - BOB
          - BRL
          - BSD
          - BTN
          - BWP
          - BYN
          - BYR
          - BZD
          - CAD
          - CDF
          - CHF
          - CLF
          - CLP
          - CNY
          - COP
          - CRC
          - CUC
          - CUP
          - CVE
          - CZK
          - DJF
          - DKK
          - DOP
          - DZD
          - EEK
          - EGP
          - ERN
          - ETB
          - EUR
          - FJD
          - FKP
          - GBP
          - GEL
          - GHS
          - GIP
          - GMD
          - GNF
          - GTQ
          - GYD
          - HKD
          - HNL
          - HRK
          - HTG
          - HUF
          - IDR
          - ILS
          - INR
          - IQD
          - IRR
          - ISK
          - JMD
          - JOD
          - JPY
          - KES
          - KGS
          - KHR
          - KMF
          - KPW
          - KRW
          - KWD
          - KYD
          - KZT
          - LAK
          - LBP
          - LKR
          - LRD
          - LSL
          - LTL
          - LVL
          - LYD
          - MAD
          - MDL
          - MGA
          - MKD
          - MMK
          - MNT
          - MOP
          - MRO
          - MRU
          - MTL
          - MUR
          - MVR
          - MWK
          - MXN
          - MYR
          - MZN
          - NAD
          - NGN
          - NIO
          - NOK
          - NPR
          - NZD
          - OMR
          - PAB
          - PEN
          - PGK
          - PHP
          - PKR
          - PLN
          - PYG
          - QAR
          - RON
          - RSD
          - RUB
          - RWF
          - SAR
          - SBD
          - SCR
          - SDG
          - SEK
          - SGD
          - SHP
          - SKK
          - SLE
          - SLL
          - SOS
          - SRD
          - SSP
          - STD
          - STN
          - SVC
          - SYP
          - SZL
          - THB
          - TJS
          - TMM
          - TMT
          - TND
          - TOP
          - TRY
          - TTD
          - TWD
          - TZS
          - UAH
          - UGX
          - USD
          - UYI
          - UYU
          - UYW
          - UZS
          - VED
          - VEF
          - VES
          - VND
          - VUV
          - WST
          - XAF
          - XCD
          - XCG
          - XOF
          - XPF
          - YER
          - ZAR
          - ZMK
          - ZMW
          - ZWD
          - ZWG
          - ZWL
          - ZWN
          - ZWR
        barcode:
          type: string
          nullable: true
        backorder_limit:
          type: number
          nullable: true
        hs_code:
          type: string
          nullable: true
        country_of_origin:
          type: string
          nullable: true
          enum:
          - AD
          - AE
          - AF
          - AG
          - AI
          - AL
          - AM
          - AO
          - AR
          - AS
          - AT
          - AU
          - AW
          - AZ
          - BA
          - BB
          - BD
          - BE
          - BF
          - BG
          - BH
          - BI
          - BJ
          - BL
          - BM
          - BN
          - BO
          - BQ
          - BR
          - BS
          - BT
          - BW
          - BY
          - BZ
          - CA
          - CC
          - CD
          - CF
          - CG
          - CH
          - CI
          - CK
          - CL
          - CM
          - CN
          - CO
          - CR
          - CU
          - CV
          - CW
          - CX
          - CY
          - CZ
          - DE
          - DJ
          - DK
          - DM
          - DO
          - DZ
          - EC
          - EE
          - EG
          - ER
          - ES
          - ET
          - FI
          - FJ
          - FK
          - FM
          - FO
          - FR
          - GA
          - GB
          - GD
          - GE
          - GF
          - GG
          - GH
          - GI
          - GL
          - GM
          - GN
          - GP
          - GQ
          - GR
          - GT
          - GU
          - GW
          - GY
          - HK
          - HN
          - HR
          - HT
          - HU
          - ID
          - IE
          - IL
          - IM
          - IN
          - IQ
          - IR
          - IS
          - IT
          - JE
          - JM
          - JO
          - JP
          - KE
          - KG
          - KH
          - KI
          - KM
          - KN
          - KP
          - KR
          - KW
          - KY
          - KZ
          - LA
          - LB
          - LC
          - LI
          - LK
          - LR
          - LS
          - LT
          - LU
          - LV
          - LY
          - MA
          - MC
          - MD
          - ME
          - MF
          - MG
          - MH
          - MK
          - ML
          - MM
          - MN
          - MO
          - MP
          - MQ
          - MR
          - MS
          - MT
          - MU
          - MV
          - MW
          - MX
          - MY
          - MZ
          - NA
          - NC
          - NE
          - NF
          - NG
          - NI
          - NL
          - 'NO'
          - NP
          - NR
          - NU
          - NZ
          - OM
          - PA
          - PE
          - PF
          - PG
          - PH
          - PK
          - PL
          - PM
          - PN
          - PR
          - PS
          - PT
          - PW
          - PY
          - QA
          - RE
          - RO
          - RS
          - RU
          - RW
          - SA
          - SB
          - SC
          - SD
          - SE
          - SG
          - SH
          - SI
          - SJ
          - SK
          - SL
          - SM
          - SN
          - SO
          - SR
          - SS
          - ST
          - SV
          - SX
          - SY
          - SZ
          - TC
          - TD
          - TG
          - TH
          - TJ
          - TK
          - TL
          - TM
          - TN
          - TO
          - TR
          - TT
          - TV
          - TW
          - TZ
          - UA
          - UG
          - US
          - UY
          - UZ
          - VA
          - VC
          - VE
          - VG
          - VI
          - VN
          - VU
          - WF
          - WS
          - YE
          - YT
          - ZA
          - ZM
          - ZW
        customs_description:
          type: string
          nullable: true
        carton_weight:
          type: string
          nullable: true
        cartons_per_pallet:
          type: number
          nullable: true
        deleted_at:
          type: string
          nullable: true
        created_at:
          type: string
        updated_at:
          type: string
        cost_price:
          type: string
          nullable: true
        preorderable:
          type: boolean
        tax_category_id:
          type: string
          nullable: true
        carton_package_type_id:
          type: string
          nullable: true
        units_per_pallet:
          type: number
          nullable: true
        available_stock:
          type: number
          nullable: true
        reserved_quantity:
          type: number
        total_on_hand:
          type: number
          nullable: true
        product_name:
          type: string
        delivery_profile_id:
          type: string
          nullable: true
        prices:
          type: array
          items:
            "$ref": "#/components/schemas/Price"
        stock_levels:
          type: array
          items:
            "$ref": "#/components/schemas/StockLevel"
      required:
      - id
      - product_id
      - sku
      - options_text
      - track_inventory
      - media_count
      - preorder_ships_at
      - thumbnail_url
      - purchasable
      - in_stock
      - backorderable
      - preorder
      - weight
      - height
      - width
      - depth
      - weight_unit
      - dimensions_unit
      - minimum_order_quantity
      - order_multiple
      - purchase_unit
      - units_per_carton
      - price
      - original_price
      - seller_id
      - option_values
      - external_references
      - metadata
      - position
      - cost_currency
      - barcode
      - backorder_limit
      - hs_code
      - country_of_origin
      - customs_description
      - carton_weight
      - cartons_per_pallet
      - deleted_at
      - created_at
      - updated_at
      - cost_price
      - preorderable
      - tax_category_id
      - carton_package_type_id
      - units_per_pallet
      - available_stock
      - reserved_quantity
      - total_on_hand
      - product_name
      - delivery_profile_id
      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
        created_at:
          type: string
        updated_at:
          type: string
        delivered_at:
          type: string
          nullable: true
        payload:
          type: object
          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
      - created_at
      - updated_at
      - delivered_at
      - payload
      - 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
    WebhookEvent:
      type: object
      properties:
        name:
          type: string
        group:
          type: string
        credential_permission:
          type: string
          nullable: true
        credential:
          type: boolean
        deprecated:
          type: boolean
        replaced_by:
          type: string
          nullable: true
      required:
      - name
      - group
      - credential_permission
      - credential
      - deprecated
      - replaced_by
      x-typelizer: true
    CommissionRuleCategoryRulePreferences:
      type: object
      properties:
        category_ids:
          type: array
          items:
            type: string
            format: prefixed-id
            pattern: "^ctg_[A-Za-z0-9]+$"
            x-spree-prefix: ctg
          default: []
      additionalProperties: false
    CommissionRuleItemTotalRulePreferences:
      type: object
      properties:
        min_amount:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          nullable: true
        max_amount:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          nullable: true
      additionalProperties: false
    CommissionRuleProductRulePreferences:
      type: object
      properties: {}
      additionalProperties: false
    CommissionRuleSellerRulePreferences:
      type: object
      properties:
        seller_ids:
          type: array
          items:
            type: string
            format: prefixed-id
            pattern: "^sel_[A-Za-z0-9]+$"
            x-spree-prefix: sel
          default: []
      additionalProperties: false
    CommissionRulePreferences:
      description: Settings of a commission rule, shaped by its `type` (see `x-spree-preferences-by-type`).
        A type an extension registers is a plain object, described by the `schema`
        its `/types` entry carries.
      anyOf:
      - "$ref": "#/components/schemas/CommissionRuleCategoryRulePreferences"
      - "$ref": "#/components/schemas/CommissionRuleItemTotalRulePreferences"
      - "$ref": "#/components/schemas/CommissionRuleProductRulePreferences"
      - "$ref": "#/components/schemas/CommissionRuleSellerRulePreferences"
      - type: object
        additionalProperties: true
      x-spree-preferences-by-type:
        category_rule: "#/components/schemas/CommissionRuleCategoryRulePreferences"
        item_total_rule: "#/components/schemas/CommissionRuleItemTotalRulePreferences"
        product_rule: "#/components/schemas/CommissionRuleProductRulePreferences"
        seller_rule: "#/components/schemas/CommissionRuleSellerRulePreferences"
    DeliveryCalculatorDigitalDeliveryPreferences:
      type: object
      properties:
        amounts:
          type: object
          additionalProperties:
            type: string
            format: money
            pattern: "^-?\\d+(\\.\\d+)?$"
          default: {}
          x-spree-property-names:
            type: string
            format: currency
            pattern: "^[A-Z]{3}$"
        amount:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
          nullable: true
        currency:
          type: string
          format: currency
          pattern: "^[A-Z]{3}$"
      additionalProperties: false
    DeliveryCalculatorFlatPercentItemTotalPreferences:
      type: object
      properties:
        flat_percent:
          type: string
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
      additionalProperties: false
    DeliveryCalculatorFlatRatePreferences:
      type: object
      properties:
        amounts:
          type: object
          additionalProperties:
            type: string
            format: money
            pattern: "^-?\\d+(\\.\\d+)?$"
          default: {}
          x-spree-property-names:
            type: string
            format: currency
            pattern: "^[A-Z]{3}$"
        amount:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
          nullable: true
        currency:
          type: string
          format: currency
          pattern: "^[A-Z]{3}$"
      additionalProperties: false
    DeliveryCalculatorFlexiRatePreferences:
      type: object
      properties:
        first_item:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
        additional_item:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
        max_items:
          type: integer
          default: 0
        currency:
          type: string
          format: currency
          pattern: "^[A-Z]{3}$"
      additionalProperties: false
    DeliveryCalculatorPerItemPreferences:
      type: object
      properties:
        amounts:
          type: object
          additionalProperties:
            type: string
            format: money
            pattern: "^-?\\d+(\\.\\d+)?$"
          default: {}
          x-spree-property-names:
            type: string
            format: currency
            pattern: "^[A-Z]{3}$"
        amount:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
          nullable: true
        currency:
          type: string
          format: currency
          pattern: "^[A-Z]{3}$"
      additionalProperties: false
    DeliveryCalculatorPriceSackPreferences:
      type: object
      properties:
        minimal_amount:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
        normal_amount:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
        discount_amount:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
        currency:
          type: string
          format: currency
          pattern: "^[A-Z]{3}$"
      additionalProperties: false
    DeliveryCalculatorPreferences:
      description: Settings of a delivery calculator, shaped by its `type` (see `x-spree-preferences-by-type`).
        A type an extension registers is a plain object, described by the `schema`
        its `/types` entry carries.
      anyOf:
      - "$ref": "#/components/schemas/DeliveryCalculatorDigitalDeliveryPreferences"
      - "$ref": "#/components/schemas/DeliveryCalculatorFlatPercentItemTotalPreferences"
      - "$ref": "#/components/schemas/DeliveryCalculatorFlatRatePreferences"
      - "$ref": "#/components/schemas/DeliveryCalculatorFlexiRatePreferences"
      - "$ref": "#/components/schemas/DeliveryCalculatorPerItemPreferences"
      - "$ref": "#/components/schemas/DeliveryCalculatorPriceSackPreferences"
      - type: object
        additionalProperties: true
      x-spree-preferences-by-type:
        digital_delivery: "#/components/schemas/DeliveryCalculatorDigitalDeliveryPreferences"
        flat_percent_item_total: "#/components/schemas/DeliveryCalculatorFlatPercentItemTotalPreferences"
        flat_rate: "#/components/schemas/DeliveryCalculatorFlatRatePreferences"
        flexi_rate: "#/components/schemas/DeliveryCalculatorFlexiRatePreferences"
        per_item: "#/components/schemas/DeliveryCalculatorPerItemPreferences"
        price_sack: "#/components/schemas/DeliveryCalculatorPriceSackPreferences"
    DeliveryMethodRuleChannelRulePreferences:
      type: object
      properties:
        channel_ids:
          type: array
          items:
            type: string
            format: prefixed-id
            pattern: "^ch_[A-Za-z0-9]+$"
            x-spree-prefix: ch
          default: []
      additionalProperties: false
    DeliveryMethodRuleCompanyRulePreferences:
      type: object
      properties:
        company_orders_only:
          type: boolean
          default: true
      additionalProperties: false
    DeliveryMethodRuleExcludedProductsRulePreferences:
      type: object
      properties: {}
      additionalProperties: false
    DeliveryMethodRuleItemTotalRulePreferences:
      type: object
      properties:
        minimum_amount:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          nullable: true
        maximum_amount:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          nullable: true
      additionalProperties: false
    DeliveryMethodRuleVolumeRulePreferences:
      type: object
      properties:
        minimum_volume:
          type: string
          pattern: "^-?\\d+(\\.\\d+)?$"
          nullable: true
        maximum_volume:
          type: string
          pattern: "^-?\\d+(\\.\\d+)?$"
          nullable: true
      additionalProperties: false
    DeliveryMethodRuleWeightRulePreferences:
      type: object
      properties:
        minimum_weight:
          type: string
          pattern: "^-?\\d+(\\.\\d+)?$"
          nullable: true
        maximum_weight:
          type: string
          pattern: "^-?\\d+(\\.\\d+)?$"
          nullable: true
      additionalProperties: false
    DeliveryMethodRulePreferences:
      description: Settings of a delivery method rule, shaped by its `type` (see `x-spree-preferences-by-type`).
        A type an extension registers is a plain object, described by the `schema`
        its `/types` entry carries.
      anyOf:
      - "$ref": "#/components/schemas/DeliveryMethodRuleChannelRulePreferences"
      - "$ref": "#/components/schemas/DeliveryMethodRuleCompanyRulePreferences"
      - "$ref": "#/components/schemas/DeliveryMethodRuleExcludedProductsRulePreferences"
      - "$ref": "#/components/schemas/DeliveryMethodRuleItemTotalRulePreferences"
      - "$ref": "#/components/schemas/DeliveryMethodRuleVolumeRulePreferences"
      - "$ref": "#/components/schemas/DeliveryMethodRuleWeightRulePreferences"
      - type: object
        additionalProperties: true
      x-spree-preferences-by-type:
        channel_rule: "#/components/schemas/DeliveryMethodRuleChannelRulePreferences"
        company_rule: "#/components/schemas/DeliveryMethodRuleCompanyRulePreferences"
        excluded_products_rule: "#/components/schemas/DeliveryMethodRuleExcludedProductsRulePreferences"
        item_total_rule: "#/components/schemas/DeliveryMethodRuleItemTotalRulePreferences"
        volume_rule: "#/components/schemas/DeliveryMethodRuleVolumeRulePreferences"
        weight_rule: "#/components/schemas/DeliveryMethodRuleWeightRulePreferences"
    IntegrationPreferences:
      description: Settings of a integration, shaped by its `type` (see `x-spree-preferences-by-type`).
        A type an extension registers is a plain object, described by the `schema`
        its `/types` entry carries.
      anyOf:
      - type: object
        additionalProperties: true
      x-spree-preferences-by-type: {}
    OrderRoutingRuleDefaultLocationPreferences:
      type: object
      properties: {}
      additionalProperties: false
    OrderRoutingRuleMinimizeSplitsPreferences:
      type: object
      properties: {}
      additionalProperties: false
    OrderRoutingRulePreferredLocationPreferences:
      type: object
      properties: {}
      additionalProperties: false
    OrderRoutingRulePreferences:
      description: Settings of a order routing rule, shaped by its `type` (see `x-spree-preferences-by-type`).
        A type an extension registers is a plain object, described by the `schema`
        its `/types` entry carries.
      anyOf:
      - "$ref": "#/components/schemas/OrderRoutingRuleDefaultLocationPreferences"
      - "$ref": "#/components/schemas/OrderRoutingRuleMinimizeSplitsPreferences"
      - "$ref": "#/components/schemas/OrderRoutingRulePreferredLocationPreferences"
      - type: object
        additionalProperties: true
      x-spree-preferences-by-type:
        default_location: "#/components/schemas/OrderRoutingRuleDefaultLocationPreferences"
        minimize_splits: "#/components/schemas/OrderRoutingRuleMinimizeSplitsPreferences"
        preferred_location: "#/components/schemas/OrderRoutingRulePreferredLocationPreferences"
    PaymentMethodBogusPreferences:
      type: object
      properties:
        dummy_key:
          type: string
          default: PUBLICKEY123
        dummy_secret_key:
          type: string
          x-spree-secret: true
          nullable: true
      additionalProperties: false
    PaymentMethodCheckPreferences:
      type: object
      properties: {}
      additionalProperties: false
    PaymentMethodCustomPaymentSourceMethodPreferences:
      type: object
      properties: {}
      additionalProperties: false
    PaymentMethodStoreCreditPreferences:
      type: object
      properties: {}
      additionalProperties: false
    PaymentMethodPreferences:
      description: Settings of a payment method, shaped by its `type` (see `x-spree-preferences-by-type`).
        A type an extension registers is a plain object, described by the `schema`
        its `/types` entry carries.
      anyOf:
      - "$ref": "#/components/schemas/PaymentMethodBogusPreferences"
      - "$ref": "#/components/schemas/PaymentMethodCheckPreferences"
      - "$ref": "#/components/schemas/PaymentMethodCustomPaymentSourceMethodPreferences"
      - "$ref": "#/components/schemas/PaymentMethodStoreCreditPreferences"
      - type: object
        additionalProperties: true
      x-spree-preferences-by-type:
        bogus: "#/components/schemas/PaymentMethodBogusPreferences"
        check: "#/components/schemas/PaymentMethodCheckPreferences"
        custom_payment_source_method: "#/components/schemas/PaymentMethodCustomPaymentSourceMethodPreferences"
        store_credit: "#/components/schemas/PaymentMethodStoreCreditPreferences"
    PriceRuleChannelRulePreferences:
      type: object
      properties:
        channel_ids:
          type: array
          items:
            type: string
            format: prefixed-id
            pattern: "^ch_[A-Za-z0-9]+$"
            x-spree-prefix: ch
          default: []
      additionalProperties: false
    PriceRuleCustomerGroupRulePreferences:
      type: object
      properties:
        customer_group_ids:
          type: array
          items:
            type: string
            format: prefixed-id
            pattern: "^cg_[A-Za-z0-9]+$"
            x-spree-prefix: cg
          default: []
      additionalProperties: false
    PriceRuleMarketRulePreferences:
      type: object
      properties:
        market_ids:
          type: array
          items:
            type: string
            format: prefixed-id
            pattern: "^mkt_[A-Za-z0-9]+$"
            x-spree-prefix: mkt
          default: []
      additionalProperties: false
    PriceRuleUserRulePreferences:
      type: object
      properties:
        user_ids:
          type: array
          items:
            type: string
            format: prefixed-id
            pattern: "^cust_[A-Za-z0-9]+$"
            x-spree-prefix: cust
          default: []
      additionalProperties: false
    PriceRuleVolumeRulePreferences:
      type: object
      properties:
        min_quantity:
          type: integer
          default: 1
        max_quantity:
          type: integer
          nullable: true
      additionalProperties: false
    PriceRulePreferences:
      description: Settings of a price rule, shaped by its `type` (see `x-spree-preferences-by-type`).
        A type an extension registers is a plain object, described by the `schema`
        its `/types` entry carries.
      anyOf:
      - "$ref": "#/components/schemas/PriceRuleChannelRulePreferences"
      - "$ref": "#/components/schemas/PriceRuleCustomerGroupRulePreferences"
      - "$ref": "#/components/schemas/PriceRuleMarketRulePreferences"
      - "$ref": "#/components/schemas/PriceRuleUserRulePreferences"
      - "$ref": "#/components/schemas/PriceRuleVolumeRulePreferences"
      - type: object
        additionalProperties: true
      x-spree-preferences-by-type:
        channel_rule: "#/components/schemas/PriceRuleChannelRulePreferences"
        customer_group_rule: "#/components/schemas/PriceRuleCustomerGroupRulePreferences"
        market_rule: "#/components/schemas/PriceRuleMarketRulePreferences"
        user_rule: "#/components/schemas/PriceRuleUserRulePreferences"
        volume_rule: "#/components/schemas/PriceRuleVolumeRulePreferences"
    PromotionCalculatorFlatPercentItemTotalPreferences:
      type: object
      properties:
        flat_percent:
          type: string
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
      additionalProperties: false
    PromotionCalculatorFlatRatePreferences:
      type: object
      properties:
        amount:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
        currency:
          type: string
          format: currency
          pattern: "^[A-Z]{3}$"
        apply_only_on_full_priced_items:
          type: boolean
          default: false
      additionalProperties: false
    PromotionCalculatorFlexiRatePreferences:
      type: object
      properties:
        first_item:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
        additional_item:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
        max_items:
          type: integer
          default: 0
        currency:
          type: string
          format: currency
          pattern: "^[A-Z]{3}$"
        apply_only_on_full_priced_items:
          type: boolean
          default: false
      additionalProperties: false
    PromotionCalculatorPercentOnLineItemPreferences:
      type: object
      properties:
        percent:
          type: string
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
        apply_only_on_full_priced_items:
          type: boolean
          default: false
      additionalProperties: false
    PromotionCalculatorTieredFlatRatePreferences:
      type: object
      properties:
        tiers:
          type: array
          items:
            type: object
            properties:
              threshold:
                type: string
                format: money
                pattern: "^-?\\d+(\\.\\d+)?$"
              value:
                type: string
                pattern: "^-?\\d+(\\.\\d+)?$"
            required:
            - threshold
            - value
            additionalProperties: false
          default: []
        base_amount:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
        currency:
          type: string
          format: currency
          pattern: "^[A-Z]{3}$"
      additionalProperties: false
    PromotionCalculatorTieredPercentPreferences:
      type: object
      properties:
        tiers:
          type: array
          items:
            type: object
            properties:
              threshold:
                type: string
                format: money
                pattern: "^-?\\d+(\\.\\d+)?$"
              value:
                type: string
                pattern: "^-?\\d+(\\.\\d+)?$"
            required:
            - threshold
            - value
            additionalProperties: false
          default: []
        base_percent:
          type: string
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '0'
      additionalProperties: false
    PromotionCalculatorPreferences:
      description: Settings of a promotion calculator, shaped by its `type` (see `x-spree-preferences-by-type`).
        A type an extension registers is a plain object, described by the `schema`
        its `/types` entry carries.
      anyOf:
      - "$ref": "#/components/schemas/PromotionCalculatorFlatPercentItemTotalPreferences"
      - "$ref": "#/components/schemas/PromotionCalculatorFlatRatePreferences"
      - "$ref": "#/components/schemas/PromotionCalculatorFlexiRatePreferences"
      - "$ref": "#/components/schemas/PromotionCalculatorPercentOnLineItemPreferences"
      - "$ref": "#/components/schemas/PromotionCalculatorTieredFlatRatePreferences"
      - "$ref": "#/components/schemas/PromotionCalculatorTieredPercentPreferences"
      - type: object
        additionalProperties: true
      x-spree-preferences-by-type:
        flat_percent_item_total: "#/components/schemas/PromotionCalculatorFlatPercentItemTotalPreferences"
        flat_rate: "#/components/schemas/PromotionCalculatorFlatRatePreferences"
        flexi_rate: "#/components/schemas/PromotionCalculatorFlexiRatePreferences"
        percent_on_line_item: "#/components/schemas/PromotionCalculatorPercentOnLineItemPreferences"
        tiered_flat_rate: "#/components/schemas/PromotionCalculatorTieredFlatRatePreferences"
        tiered_percent: "#/components/schemas/PromotionCalculatorTieredPercentPreferences"
    PromotionRuleCategoryPreferences:
      type: object
      properties:
        match_policy:
          type: string
          enum:
          - any
          - all
          default: any
      additionalProperties: false
    PromotionRuleChannelPreferences:
      type: object
      properties:
        channel_ids:
          type: array
          items:
            type: string
            format: prefixed-id
            pattern: "^ch_[A-Za-z0-9]+$"
            x-spree-prefix: ch
          default: []
      additionalProperties: false
    PromotionRuleCountryPreferences:
      type: object
      properties:
        country_codes:
          type: array
          items:
            type: string
            format: iso-country
            pattern: "^[A-Z]{2}$"
          default: []
        country_id:
          type: integer
          nullable: true
        country_code:
          type: string
          format: iso-country
          pattern: "^[A-Z]{2}$"
          nullable: true
      additionalProperties: false
    PromotionRuleCurrencyPreferences:
      type: object
      properties:
        currency:
          type: string
          format: currency
          pattern: "^[A-Z]{3}$"
          nullable: true
      additionalProperties: false
    PromotionRuleCustomerPreferences:
      type: object
      properties: {}
      additionalProperties: false
    PromotionRuleCustomerGroupPreferences:
      type: object
      properties:
        customer_group_ids:
          type: array
          items:
            type: string
            format: prefixed-id
            pattern: "^cg_[A-Za-z0-9]+$"
            x-spree-prefix: cg
          default: []
      additionalProperties: false
    PromotionRuleCustomerLoggedInPreferences:
      type: object
      properties: {}
      additionalProperties: false
    PromotionRuleFirstOrderPreferences:
      type: object
      properties: {}
      additionalProperties: false
    PromotionRuleItemTotalPreferences:
      type: object
      properties:
        amount_min:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          default: '100'
        operator_min:
          type: string
          default: ">"
        amount_max:
          type: string
          format: money
          pattern: "^-?\\d+(\\.\\d+)?$"
          nullable: true
        operator_max:
          type: string
          default: "<"
      additionalProperties: false
    PromotionRuleMarketPreferences:
      type: object
      properties:
        market_ids:
          type: array
          items:
            type: string
            format: prefixed-id
            pattern: "^mkt_[A-Za-z0-9]+$"
            x-spree-prefix: mkt
          default: []
      additionalProperties: false
    PromotionRuleOneUsePerUserPreferences:
      type: object
      properties: {}
      additionalProperties: false
    PromotionRuleOptionValuePreferences:
      type: object
      properties:
        match_policy:
          type: string
          enum:
          - any
          default: any
        eligible_values:
          type: array
          items:
            type: string
            format: prefixed-id
            pattern: "^optval_[A-Za-z0-9]+$"
            x-spree-prefix: optval
          default: []
      additionalProperties: false
    PromotionRuleProductPreferences:
      type: object
      properties:
        match_policy:
          type: string
          enum:
          - any
          - all
          - none
          default: any
      additionalProperties: false
    PromotionRulePreferences:
      description: Settings of a promotion rule, shaped by its `type` (see `x-spree-preferences-by-type`).
        A type an extension registers is a plain object, described by the `schema`
        its `/types` entry carries.
      anyOf:
      - "$ref": "#/components/schemas/PromotionRuleCategoryPreferences"
      - "$ref": "#/components/schemas/PromotionRuleChannelPreferences"
      - "$ref": "#/components/schemas/PromotionRuleCountryPreferences"
      - "$ref": "#/components/schemas/PromotionRuleCurrencyPreferences"
      - "$ref": "#/components/schemas/PromotionRuleCustomerPreferences"
      - "$ref": "#/components/schemas/PromotionRuleCustomerGroupPreferences"
      - "$ref": "#/components/schemas/PromotionRuleCustomerLoggedInPreferences"
      - "$ref": "#/components/schemas/PromotionRuleFirstOrderPreferences"
      - "$ref": "#/components/schemas/PromotionRuleItemTotalPreferences"
      - "$ref": "#/components/schemas/PromotionRuleMarketPreferences"
      - "$ref": "#/components/schemas/PromotionRuleOneUsePerUserPreferences"
      - "$ref": "#/components/schemas/PromotionRuleOptionValuePreferences"
      - "$ref": "#/components/schemas/PromotionRuleProductPreferences"
      - type: object
        additionalProperties: true
      x-spree-preferences-by-type:
        category: "#/components/schemas/PromotionRuleCategoryPreferences"
        channel: "#/components/schemas/PromotionRuleChannelPreferences"
        country: "#/components/schemas/PromotionRuleCountryPreferences"
        currency: "#/components/schemas/PromotionRuleCurrencyPreferences"
        customer: "#/components/schemas/PromotionRuleCustomerPreferences"
        customer_group: "#/components/schemas/PromotionRuleCustomerGroupPreferences"
        customer_logged_in: "#/components/schemas/PromotionRuleCustomerLoggedInPreferences"
        first_order: "#/components/schemas/PromotionRuleFirstOrderPreferences"
        item_total: "#/components/schemas/PromotionRuleItemTotalPreferences"
        market: "#/components/schemas/PromotionRuleMarketPreferences"
        one_use_per_user: "#/components/schemas/PromotionRuleOneUsePerUserPreferences"
        option_value: "#/components/schemas/PromotionRuleOptionValuePreferences"
        product: "#/components/schemas/PromotionRuleProductPreferences"
    SellerRequirementAcceptTermsPreferences:
      type: object
      properties:
        terms_body:
          type: string
          x-spree-widget: textarea
          nullable: true
        terms_effective_from:
          type: string
          format: date
          nullable: true
        terms_url:
          type: string
          nullable: true
      additionalProperties: false
    SellerRequirementAttestationPreferences:
      type: object
      properties: {}
      additionalProperties: false
    SellerRequirementBillingAddressPreferences:
      type: object
      properties: {}
      additionalProperties: false
    SellerRequirementCompleteProfilePreferences:
      type: object
      properties:
        require_about:
          type: boolean
          default: true
        require_logo:
          type: boolean
          default: true
        require_cover_photo:
          type: boolean
          default: false
        require_contact_email:
          type: boolean
          default: false
      additionalProperties: false
    SellerRequirementDeliveryMethodPreferences:
      type: object
      properties: {}
      additionalProperties: false
    SellerRequirementDocumentPreferences:
      type: object
      properties: {}
      additionalProperties: false
    SellerRequirementMinimumProductsPreferences:
      type: object
      properties:
        minimum_count:
          type: integer
          default: 1
      additionalProperties: false
    SellerRequirementOperatorReviewPreferences:
      type: object
      properties: {}
      additionalProperties: false
    SellerRequirementPackageTypePreferences:
      type: object
      properties: {}
      additionalProperties: false
    SellerRequirementPayoutAccountPreferences:
      type: object
      properties: {}
      additionalProperties: false
    SellerRequirementPolicyPreferences:
      type: object
      properties: {}
      additionalProperties: false
    SellerRequirementRequiredCustomFieldsPreferences:
      type: object
      properties: {}
      additionalProperties: false
    SellerRequirementReturnsAddressPreferences:
      type: object
      properties: {}
      additionalProperties: false
    SellerRequirementPreferences:
      description: Settings of a seller requirement, shaped by its `type` (see `x-spree-preferences-by-type`).
        A type an extension registers is a plain object, described by the `schema`
        its `/types` entry carries.
      anyOf:
      - "$ref": "#/components/schemas/SellerRequirementAcceptTermsPreferences"
      - "$ref": "#/components/schemas/SellerRequirementAttestationPreferences"
      - "$ref": "#/components/schemas/SellerRequirementBillingAddressPreferences"
      - "$ref": "#/components/schemas/SellerRequirementCompleteProfilePreferences"
      - "$ref": "#/components/schemas/SellerRequirementDeliveryMethodPreferences"
      - "$ref": "#/components/schemas/SellerRequirementDocumentPreferences"
      - "$ref": "#/components/schemas/SellerRequirementMinimumProductsPreferences"
      - "$ref": "#/components/schemas/SellerRequirementOperatorReviewPreferences"
      - "$ref": "#/components/schemas/SellerRequirementPackageTypePreferences"
      - "$ref": "#/components/schemas/SellerRequirementPayoutAccountPreferences"
      - "$ref": "#/components/schemas/SellerRequirementPolicyPreferences"
      - "$ref": "#/components/schemas/SellerRequirementRequiredCustomFieldsPreferences"
      - "$ref": "#/components/schemas/SellerRequirementReturnsAddressPreferences"
      - type: object
        additionalProperties: true
      x-spree-preferences-by-type:
        accept_terms: "#/components/schemas/SellerRequirementAcceptTermsPreferences"
        attestation: "#/components/schemas/SellerRequirementAttestationPreferences"
        billing_address: "#/components/schemas/SellerRequirementBillingAddressPreferences"
        complete_profile: "#/components/schemas/SellerRequirementCompleteProfilePreferences"
        delivery_method: "#/components/schemas/SellerRequirementDeliveryMethodPreferences"
        document: "#/components/schemas/SellerRequirementDocumentPreferences"
        minimum_products: "#/components/schemas/SellerRequirementMinimumProductsPreferences"
        operator_review: "#/components/schemas/SellerRequirementOperatorReviewPreferences"
        package_type: "#/components/schemas/SellerRequirementPackageTypePreferences"
        payout_account: "#/components/schemas/SellerRequirementPayoutAccountPreferences"
        policy: "#/components/schemas/SellerRequirementPolicyPreferences"
        required_custom_fields: "#/components/schemas/SellerRequirementRequiredCustomFieldsPreferences"
        returns_address: "#/components/schemas/SellerRequirementReturnsAddressPreferences"
    DeliveryMethodCalculator:
      type: object
      description: How the delivery method prices a shipment
      properties:
        type:
          type: string
          example: flat_rate
          description: Wire shorthand for the calculator subclass
        preferences:
          "$ref": "#/components/schemas/DeliveryCalculatorPreferences"
      required:
      - type
      - preferences
    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
        preferences:
          "$ref": "#/components/schemas/PromotionCalculatorPreferences"
      required:
      - type
      - preferences
    CurrencyCode:
      type: string
      enum:
      - AED
      - AFN
      - ALL
      - AMD
      - ANG
      - AOA
      - ARS
      - AUD
      - AWG
      - AZN
      - BAM
      - BBD
      - BDT
      - BGN
      - BHD
      - BIF
      - BMD
      - BND
      - BOB
      - BRL
      - BSD
      - BTN
      - BWP
      - BYN
      - BYR
      - BZD
      - CAD
      - CDF
      - CHF
      - CLF
      - CLP
      - CNY
      - COP
      - CRC
      - CUC
      - CUP
      - CVE
      - CZK
      - DJF
      - DKK
      - DOP
      - DZD
      - EEK
      - EGP
      - ERN
      - ETB
      - EUR
      - FJD
      - FKP
      - GBP
      - GEL
      - GHS
      - GIP
      - GMD
      - GNF
      - GTQ
      - GYD
      - HKD
      - HNL
      - HRK
      - HTG
      - HUF
      - IDR
      - ILS
      - INR
      - IQD
      - IRR
      - ISK
      - JMD
      - JOD
      - JPY
      - KES
      - KGS
      - KHR
      - KMF
      - KPW
      - KRW
      - KWD
      - KYD
      - KZT
      - LAK
      - LBP
      - LKR
      - LRD
      - LSL
      - LTL
      - LVL
      - LYD
      - MAD
      - MDL
      - MGA
      - MKD
      - MMK
      - MNT
      - MOP
      - MRO
      - MRU
      - MTL
      - MUR
      - MVR
      - MWK
      - MXN
      - MYR
      - MZN
      - NAD
      - NGN
      - NIO
      - NOK
      - NPR
      - NZD
      - OMR
      - PAB
      - PEN
      - PGK
      - PHP
      - PKR
      - PLN
      - PYG
      - QAR
      - RON
      - RSD
      - RUB
      - RWF
      - SAR
      - SBD
      - SCR
      - SDG
      - SEK
      - SGD
      - SHP
      - SKK
      - SLE
      - SLL
      - SOS
      - SRD
      - SSP
      - STD
      - STN
      - SVC
      - SYP
      - SZL
      - THB
      - TJS
      - TMM
      - TMT
      - TND
      - TOP
      - TRY
      - TTD
      - TWD
      - TZS
      - UAH
      - UGX
      - USD
      - UYI
      - UYU
      - UYW
      - UZS
      - VED
      - VEF
      - VES
      - VND
      - VUV
      - WST
      - XAF
      - XCD
      - XCG
      - XOF
      - XPF
      - YER
      - ZAR
      - ZMK
      - ZMW
      - ZWD
      - ZWG
      - ZWL
      - ZWN
      - ZWR
    CountryCode:
      type: string
      enum:
      - AD
      - AE
      - AF
      - AG
      - AI
      - AL
      - AM
      - AO
      - AR
      - AS
      - AT
      - AU
      - AW
      - AZ
      - BA
      - BB
      - BD
      - BE
      - BF
      - BG
      - BH
      - BI
      - BJ
      - BL
      - BM
      - BN
      - BO
      - BQ
      - BR
      - BS
      - BT
      - BW
      - BY
      - BZ
      - CA
      - CC
      - CD
      - CF
      - CG
      - CH
      - CI
      - CK
      - CL
      - CM
      - CN
      - CO
      - CR
      - CU
      - CV
      - CW
      - CX
      - CY
      - CZ
      - DE
      - DJ
      - DK
      - DM
      - DO
      - DZ
      - EC
      - EE
      - EG
      - ER
      - ES
      - ET
      - FI
      - FJ
      - FK
      - FM
      - FO
      - FR
      - GA
      - GB
      - GD
      - GE
      - GF
      - GG
      - GH
      - GI
      - GL
      - GM
      - GN
      - GP
      - GQ
      - GR
      - GT
      - GU
      - GW
      - GY
      - HK
      - HN
      - HR
      - HT
      - HU
      - ID
      - IE
      - IL
      - IM
      - IN
      - IQ
      - IR
      - IS
      - IT
      - JE
      - JM
      - JO
      - JP
      - KE
      - KG
      - KH
      - KI
      - KM
      - KN
      - KP
      - KR
      - KW
      - KY
      - KZ
      - LA
      - LB
      - LC
      - LI
      - LK
      - LR
      - LS
      - LT
      - LU
      - LV
      - LY
      - MA
      - MC
      - MD
      - ME
      - MF
      - MG
      - MH
      - MK
      - ML
      - MM
      - MN
      - MO
      - MP
      - MQ
      - MR
      - MS
      - MT
      - MU
      - MV
      - MW
      - MX
      - MY
      - MZ
      - NA
      - NC
      - NE
      - NF
      - NG
      - NI
      - NL
      - 'NO'
      - NP
      - NR
      - NU
      - NZ
      - OM
      - PA
      - PE
      - PF
      - PG
      - PH
      - PK
      - PL
      - PM
      - PN
      - PR
      - PS
      - PT
      - PW
      - PY
      - QA
      - RE
      - RO
      - RS
      - RU
      - RW
      - SA
      - SB
      - SC
      - SD
      - SE
      - SG
      - SH
      - SI
      - SJ
      - SK
      - SL
      - SM
      - SN
      - SO
      - SR
      - SS
      - ST
      - SV
      - SX
      - SY
      - SZ
      - TC
      - TD
      - TG
      - TH
      - TJ
      - TK
      - TL
      - TM
      - TN
      - TO
      - TR
      - TT
      - TV
      - TW
      - TZ
      - UA
      - UG
      - US
      - UY
      - UZ
      - VA
      - VC
      - VE
      - VG
      - VI
      - VN
      - VU
      - WF
      - WS
      - YE
      - YT
      - ZA
      - ZM
      - ZW
    LocaleCode:
      type: string
      enum:
      - aa
      - ab
      - ae
      - af
      - ak
      - am
      - an
      - ar
      - as
      - av
      - ay
      - az
      - ba
      - be
      - bg
      - bh
      - bi
      - bm
      - bn
      - bo
      - br
      - bs
      - ca
      - ce
      - ch
      - co
      - cr
      - cs
      - cu
      - cv
      - cy
      - da
      - de
      - de-AT
      - de-CH
      - dv
      - dz
      - ee
      - el
      - en
      - en-AU
      - en-CA
      - en-GB
      - en-IN
      - en-NZ
      - en-US
      - eo
      - es
      - es-419
      - es-CL
      - es-EC
      - es-MX
      - et
      - eu
      - fa
      - ff
      - fi
      - fj
      - fo
      - fr
      - fr-CA
      - fy
      - ga
      - gd
      - gl
      - gn
      - gu
      - gv
      - ha
      - he
      - hi
      - ho
      - hr
      - ht
      - hu
      - hy
      - hz
      - ia
      - id
      - ie
      - ig
      - ii
      - ik
      - io
      - is
      - it
      - iu
      - ja
      - jv
      - ka
      - kg
      - ki
      - kj
      - kk
      - kl
      - km
      - kn
      - ko
      - kr
      - ks
      - ku
      - kv
      - kw
      - ky
      - la
      - lb
      - lg
      - li
      - ln
      - lo
      - lt
      - lu
      - lv
      - mg
      - mh
      - mi
      - mk
      - ml
      - mn
      - mr
      - ms
      - mt
      - my
      - na
      - nb
      - nd
      - ne
      - ng
      - nl
      - nn
      - 'no'
      - nr
      - nv
      - ny
      - oc
      - oj
      - om
      - or
      - os
      - pa
      - pi
      - pl
      - ps
      - pt
      - pt-BR
      - pt-PT
      - qu
      - rm
      - rn
      - ro
      - ru
      - rw
      - sa
      - sc
      - sd
      - se
      - sg
      - si
      - sk
      - sl
      - sl-SI
      - sm
      - sn
      - so
      - sq
      - sr
      - ss
      - st
      - su
      - sv
      - sw
      - ta
      - te
      - tg
      - th
      - ti
      - tk
      - tl
      - tn
      - to
      - tr
      - ts
      - tt
      - tw
      - ty
      - ug
      - uk
      - ur
      - uz
      - ve
      - vi
      - vo
      - wa
      - wo
      - xh
      - yi
      - yo
      - za
      - zh-CN
      - zh-HK
      - zh-TW
      - zu
    DimensionUnit:
      type: string
      enum:
      - mm
      - cm
      - in
      - ft
    WeightUnit:
      type: string
      enum:
      - g
      - kg
      - lb
      - oz
    TimeZone:
      anyOf:
      - type: string
        enum:
        - Africa/Algiers
        - Africa/Cairo
        - Africa/Casablanca
        - Africa/Harare
        - Africa/Johannesburg
        - Africa/Monrovia
        - Africa/Nairobi
        - America/Argentina/Buenos_Aires
        - America/Asuncion
        - America/Bogota
        - America/Caracas
        - America/Chicago
        - America/Chihuahua
        - America/Denver
        - America/Guatemala
        - America/Guyana
        - America/Halifax
        - America/Indiana/Indianapolis
        - America/Juneau
        - America/La_Paz
        - America/Lima
        - America/Los_Angeles
        - America/Mazatlan
        - America/Mexico_City
        - America/Monterrey
        - America/Montevideo
        - America/New_York
        - America/Nuuk
        - America/Phoenix
        - America/Puerto_Rico
        - America/Regina
        - America/Santiago
        - America/Sao_Paulo
        - America/St_Johns
        - America/Tijuana
        - Asia/Almaty
        - Asia/Baghdad
        - Asia/Baku
        - Asia/Bangkok
        - Asia/Chongqing
        - Asia/Colombo
        - Asia/Dhaka
        - Asia/Hong_Kong
        - Asia/Irkutsk
        - Asia/Jakarta
        - Asia/Jerusalem
        - Asia/Kabul
        - Asia/Kamchatka
        - Asia/Karachi
        - Asia/Kathmandu
        - Asia/Kolkata
        - Asia/Krasnoyarsk
        - Asia/Kuala_Lumpur
        - Asia/Kuwait
        - Asia/Magadan
        - Asia/Muscat
        - Asia/Novosibirsk
        - Asia/Riyadh
        - Asia/Seoul
        - Asia/Shanghai
        - Asia/Singapore
        - Asia/Srednekolymsk
        - Asia/Taipei
        - Asia/Tashkent
        - Asia/Tbilisi
        - Asia/Tehran
        - Asia/Tokyo
        - Asia/Ulaanbaatar
        - Asia/Urumqi
        - Asia/Vladivostok
        - Asia/Yakutsk
        - Asia/Yangon
        - Asia/Yekaterinburg
        - Asia/Yerevan
        - Atlantic/Azores
        - Atlantic/Cape_Verde
        - Atlantic/South_Georgia
        - Australia/Adelaide
        - Australia/Brisbane
        - Australia/Canberra
        - Australia/Darwin
        - Australia/Hobart
        - Australia/Melbourne
        - Australia/Perth
        - Australia/Sydney
        - Etc/GMT+12
        - Europe/Amsterdam
        - Europe/Athens
        - Europe/Belgrade
        - Europe/Berlin
        - Europe/Bratislava
        - Europe/Brussels
        - Europe/Bucharest
        - Europe/Budapest
        - Europe/Copenhagen
        - Europe/Dublin
        - Europe/Helsinki
        - Europe/Istanbul
        - Europe/Kaliningrad
        - Europe/Kyiv
        - Europe/Lisbon
        - Europe/Ljubljana
        - Europe/London
        - Europe/Madrid
        - Europe/Minsk
        - Europe/Moscow
        - Europe/Paris
        - Europe/Prague
        - Europe/Riga
        - Europe/Rome
        - Europe/Samara
        - Europe/Sarajevo
        - Europe/Skopje
        - Europe/Sofia
        - Europe/Stockholm
        - Europe/Tallinn
        - Europe/Vienna
        - Europe/Vilnius
        - Europe/Volgograd
        - Europe/Warsaw
        - Europe/Zagreb
        - Europe/Zurich
        - Pacific/Apia
        - Pacific/Auckland
        - Pacific/Chatham
        - Pacific/Fakaofo
        - Pacific/Fiji
        - Pacific/Guadalcanal
        - Pacific/Guam
        - Pacific/Honolulu
        - Pacific/Majuro
        - Pacific/Midway
        - Pacific/Noumea
        - Pacific/Pago_Pago
        - Pacific/Port_Moresby
        - Pacific/Tongatapu
        - UTC
      - type: string
      description: Common IANA time zones; any other IANA time zone identifier is
        accepted too.
    AddressInputParams:
      type: object
      properties:
        first_name:
          type: string
        last_name:
          type: string
        company:
          type: string
        address1:
          type: string
        address2:
          type: string
        city:
          type: string
        postal_code:
          type: string
        phone:
          type: string
        label:
          type: string
        country_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          description: ISO 3166-1 alpha-2 code, such as `US`.
          example: US
        state_code:
          type: string
          description: The state or province abbreviation, such as `NY`.
          example: NY
        state_name:
          type: string
          description: For countries without states in the database.
        alternative_phone:
          type: string
    AdminUserUpdateParams:
      type: object
      properties:
        first_name:
          type: string
        last_name:
          type: string
        role_ids:
          type: array
          items:
            type: string
          description: Role IDs of the current store the user should hold. Replaces
            the user's roles on this store; an empty list removes them all.
    AllowedOriginCreateParams:
      type: object
      properties:
        origin:
          type: string
          description: 'Origin to allow in admin CORS preflight checks: a bare `scheme://host[:port]`
            (no path, query or fragment) using `http` or `https`.'
          example: https://admin.example.com
      required:
      - origin
    AllowedOriginUpdateParams:
      type: object
      properties:
        origin:
          type: string
          description: 'Origin to allow in admin CORS preflight checks: a bare `scheme://host[:port]`
            (no path, query or fragment) using `http` or `https`.'
          example: https://admin.example.com
    ApiKeyCreateParams:
      type: object
      properties:
        name:
          type: string
        key_type:
          type: string
          enum:
          - publishable
          - secret
        scopes:
          type: array
          items:
            type: string
          description: 'Required for secret keys. You can only grant scopes you hold
            yourself. Fixed once created: to change them, create a new key and revoke
            the old one.'
          example:
          - read_orders
          - write_products
        channel_id:
          type: string
          description: Binds a publishable key to one channel of the store (`ch_...`),
            so it rejects requests for other channels. Fixed once created; omit it
            for a store-wide key.
      required:
      - name
      - key_type
    ApiKeyUpdateParams:
      type: object
      properties:
        name:
          type: string
      required:
      - name
    BulkTagsParams:
      type: object
      properties:
        ids:
          type: array
          items:
            type: string
          description: The records to change. Records the caller cannot update are
            skipped; an empty list changes nothing.
        tags:
          type: array
          items:
            type: string
          example:
          - vip
          - wholesale
      required:
      - ids
      - tags
    CatalogAssignParams:
      type: object
      properties:
        assignable_type:
          type: string
          enum:
          - customer_group
          - company
          description: Buyer audiences only. A company assignment covers its subtree.
          example: company
        assignable_id:
          type: string
          example: comp_86Rf07xd4z
      required:
      - assignable_type
      - assignable_id
    CatalogAssignmentParams:
      type: object
      properties:
        assignable_type:
          type: string
          enum:
          - customer_group
          - company
          description: Buyer audiences only. A company assignment covers its subtree.
          example: company
        assignable_id:
          type: string
          example: comp_86Rf07xd4z
      required:
      - assignable_type
      - assignable_id
    CatalogCreateParams:
      type: object
      properties:
        name:
          type: string
          example: VIP Assortment
        description:
          type: string
          description: Internal note on what the agreement is, never shown to shoppers.
          nullable: true
        active:
          type: boolean
          example: true
        position:
          type: integer
        minimum_order_quantity:
          type: integer
          description: The catalog-wide quantity terms, between a variant's own rule
            and a per-variant override. Null leaves the field to the variant's own
            rule.
          nullable: true
        order_multiple:
          type: integer
          description: The catalog-wide quantity terms, between a variant's own rule
            and a per-variant override. Null leaves the field to the variant's own
            rule.
          nullable: true
        metadata:
          type: object
          additionalProperties: true
        assignments:
          type: array
          items:
            "$ref": "#/components/schemas/CatalogAssignmentParams"
          description: The whole audience. An entry left out is withdrawn; omitting
            the key leaves the audience alone.
        order_minimums:
          type: array
          items:
            "$ref": "#/components/schemas/CatalogOrderMinimumParams"
          description: The whole order-minimum set. A currency left out has its minimum
            lifted; omitting the key leaves them alone.
        price_list:
          allOf:
          - "$ref": "#/components/schemas/CatalogPriceListParams"
          description: 'The price list this catalog prices through, written inline:
            an object creates the owned list or updates it. Null deletes the list
            (a soft delete). Omit the key, or send `{}`, to leave the pricing alone.
            A catalog with an empty assortment prices without hiding anything; curate
            or import products to make it restrictive.'
          nullable: true
      required:
      - name
    CatalogOrderMinimumParams:
      type: object
      properties:
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          description: ISO 4217 code. Required on create; one minimum per currency.
          example: USD
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '500.00'
    CatalogPriceListParams:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
          nullable: true
        status:
          type: string
        match_policy:
          type: string
        starts_at:
          type: string
          format: date-time
          nullable: true
        ends_at:
          type: string
          format: date-time
          nullable: true
        price_adjustment_percentage:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: 'Signed: negative discounts off base prices, positive marks
            up.'
          example: "-15.0"
          nullable: true
        adjust_compare_at:
          type: boolean
        rules:
          type: array
          items:
            "$ref": "#/components/schemas/PriceListRuleParams"
          description: Contextual rules, in practice a `volume_rule`. Audience rules
            are left as they are, and an empty list clears the contextual rules.
        prices:
          type: array
          items:
            "$ref": "#/components/schemas/PriceListPriceOverrideParams"
          description: Explicit per-variant amounts. An empty list clears them, which
            is what switching to a percentage sends.
        price_adjustment_tiers:
          type: array
          items:
            "$ref": "#/components/schemas/PriceAdjustmentTierParams"
          description: Quantity bands on the percentage. The payload is the whole
            ladder, so an empty list clears it.
    CatalogProductTermsParams:
      type: object
      properties:
        terms:
          type: object
          additionalProperties: true
          description: 'Quantity terms keyed by product: `{ minimum_order_quantity,
            order_multiple }`, each a whole number or null. A product whose pair is
            both null has its terms cleared; a product not yet in the assortment is
            added.'
          example:
            prod_abc123:
              minimum_order_quantity: 48
              order_multiple: 24
      required:
      - terms
    CatalogUpdateParams:
      type: object
      properties:
        name:
          type: string
          example: VIP Assortment
        description:
          type: string
          description: Internal note on what the agreement is, never shown to shoppers.
          nullable: true
        active:
          type: boolean
          example: true
        position:
          type: integer
        minimum_order_quantity:
          type: integer
          description: The catalog-wide quantity terms, between a variant's own rule
            and a per-variant override. Null leaves the field to the variant's own
            rule.
          nullable: true
        order_multiple:
          type: integer
          description: The catalog-wide quantity terms, between a variant's own rule
            and a per-variant override. Null leaves the field to the variant's own
            rule.
          nullable: true
        metadata:
          type: object
          additionalProperties: true
        assignments:
          type: array
          items:
            "$ref": "#/components/schemas/CatalogAssignmentParams"
          description: The whole audience. An entry left out is withdrawn; omitting
            the key leaves the audience alone.
        order_minimums:
          type: array
          items:
            "$ref": "#/components/schemas/CatalogOrderMinimumParams"
          description: The whole order-minimum set. A currency left out has its minimum
            lifted; omitting the key leaves them alone.
        price_list:
          allOf:
          - "$ref": "#/components/schemas/CatalogPriceListParams"
          description: 'The price list this catalog prices through, written inline:
            an object creates the owned list or updates it. Null deletes the list
            (a soft delete). Omit the key, or send `{}`, to leave the pricing alone.
            A catalog with an empty assortment prices without hiding anything; curate
            or import products to make it restrictive.'
          nullable: true
    CategoryCreateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        name:
          type: string
          example: Shirts
        parent_id:
          type: string
          description: 'The parent category. Omitted or null, a new category goes
            to the top level and an existing one keeps its parent: moving one to the
            top level is the reposition endpoint.'
          example: ctg_abc123
          nullable: true
        description:
          type: string
          description: Rich text HTML. Reads come back as this (plain text) plus `description_html`.
        permalink:
          type: string
        meta_title:
          type: string
        meta_description:
          type: string
        meta_keywords:
          type: string
        image_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for the landscape image,
            or null to remove it.
          nullable: true
        square_image_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for the square image, or
            null to remove it.
          nullable: true
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomFieldValueParams"
          description: Custom field values, each validated against its definition.
      required:
      - name
    CategoryRepositionParams:
      type: object
      properties:
        new_parent_id:
          type: string
          description: The new parent. Omit or null to move the category to the top
            level.
          nullable: true
        new_position:
          type: integer
          description: 0-based index among the new parent's children.
          example: 0
      required:
      - new_position
    CategoryUpdateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        name:
          type: string
          example: Shirts
        parent_id:
          type: string
          description: 'The parent category. Omitted or null, a new category goes
            to the top level and an existing one keeps its parent: moving one to the
            top level is the reposition endpoint.'
          example: ctg_abc123
          nullable: true
        description:
          type: string
          description: Rich text HTML. Reads come back as this (plain text) plus `description_html`.
        permalink:
          type: string
        meta_title:
          type: string
        meta_description:
          type: string
        meta_keywords:
          type: string
        image_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for the landscape image,
            or null to remove it.
          nullable: true
        square_image_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for the square image, or
            null to remove it.
          nullable: true
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomFieldValueParams"
          description: Custom field values, each validated against its definition.
    ChannelAddProductsParams:
      type: object
      properties:
        product_ids:
          type: array
          items:
            type: string
        published_at:
          type: string
          format: date-time
          description: When the publications go live. Null means immediately.
          nullable: true
        unpublished_at:
          type: string
          format: date-time
          description: When the publications come down. Null means never.
          nullable: true
      required:
      - product_ids
    ChannelCreateParams:
      type: object
      properties:
        name:
          type: string
          example: Point of Sale
        code:
          type: string
          description: URL-safe slug, derived from `name` when blank (`Point of Sale`
            becomes `point-of-sale`).
          example: pos
        active:
          type: boolean
        default:
          type: boolean
        order_routing_strategy:
          type: string
          description: 'Order routing strategy shorthand (built-in: `rules`). Null
            inherits the store setting.'
          nullable: true
        storefront_access:
          type: string
          enum:
          - public
          - prices_hidden
          - login_required
          description: What anonymous visitors can see. Null inherits the store setting.
          nullable: true
        guest_checkout:
          type: boolean
          description: Whether guests can check out without an account. Null inherits
            the store setting.
          nullable: true
        default_catalog_id:
          type: string
          description: Catalog (`cat_...`) shown to shoppers no company or customer
            group catalog covers. Null means every product published on the channel.
          nullable: true
        stock_location_ids:
          type: array
          items:
            type: string
          description: Stock locations (`sloc_...`) that fulfill this channel. Replaces
            the whole set; an empty list means every location of the store.
      required:
      - name
    ChannelRemoveProductsParams:
      type: object
      properties:
        product_ids:
          type: array
          items:
            type: string
      required:
      - product_ids
    ChannelUpdateParams:
      type: object
      properties:
        name:
          type: string
          example: Point of Sale
        code:
          type: string
          description: URL-safe slug, derived from `name` when blank (`Point of Sale`
            becomes `point-of-sale`).
          example: pos
        active:
          type: boolean
        default:
          type: boolean
        order_routing_strategy:
          type: string
          description: 'Order routing strategy shorthand (built-in: `rules`). Null
            inherits the store setting.'
          nullable: true
        storefront_access:
          type: string
          enum:
          - public
          - prices_hidden
          - login_required
          description: What anonymous visitors can see. Null inherits the store setting.
          nullable: true
        guest_checkout:
          type: boolean
          description: Whether guests can check out without an account. Null inherits
            the store setting.
          nullable: true
        default_catalog_id:
          type: string
          description: Catalog (`cat_...`) shown to shoppers no company or customer
            group catalog covers. Null means every product published on the channel.
          nullable: true
        stock_location_ids:
          type: array
          items:
            type: string
          description: Stock locations (`sloc_...`) that fulfill this channel. Replaces
            the whole set; an empty list means every location of the store.
    ClaimCancelParams:
      type: object
      properties:
        reason:
          type: string
          description: A note on why the claim was canceled.
    ClaimCreateParams:
      type: object
      properties:
        items:
          type: array
          items:
            type: object
            properties:
              line_item_id:
                type: string
              quantity:
                type: integer
              description:
                type: string
              send_replacement:
                type: boolean
              replacement_variant_id:
                type: string
                description: Defaults to the variant that was bought.
              refund_amount:
                type: string
                format: decimal
                pattern: "^-?\\d+(\\.\\d+)?$"
            required:
            - line_item_id
            - quantity
          description: Affected items, and how each should be made right.
        reason_id:
          type: string
          description: One of the store's claim reasons.
        memo:
          type: string
      required:
      - items
    ClaimDenyParams:
      type: object
      properties:
        reason:
          type: string
          description: Recorded on the claim for the customer.
    ClaimResolveParams:
      type: object
      properties:
        resolution:
          type: string
          enum:
          - refund
          - replacement
          - refund_and_replacement
          description: Money back, a replacement shipment, or both.
        refund_method:
          type: string
          enum:
          - original_payment
          - store_credit
          description: Defaults to `store_credit`.
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: Defaults to the claim total.
        replacement_line_item_ids:
          type: array
          items:
            type: string
          description: Which claim lines to send a replacement for. Omit to keep what
            the claim was opened with.
      required:
      - resolution
    ClaimUpdateParams:
      type: object
      properties:
        reason_id:
          type: string
          description: One of the store's claim reasons.
        memo:
          type: string
        metadata:
          type: object
          additionalProperties: true
    CollectionCreateParams:
      type: object
      properties:
        name:
          type: string
          example: On Sale
        description:
          type: string
          description: Rich text HTML. Reads come back as this (plain text) plus `description_html`.
        permalink:
          type: string
        position:
          type: integer
          description: 1-based position among the store's collections; the server
            shifts its siblings. The nested products reposition endpoints, unlike
            this, take 0-based indexes.
        meta_title:
          type: string
        meta_description:
          type: string
        meta_keywords:
          type: string
        image_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for the landscape image,
            or null to remove it.
          nullable: true
        square_image_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for the square image, or
            null to remove it.
          nullable: true
        automatic:
          type: boolean
          description: When true, membership is materialized from `rules` instead
            of curated by hand.
        rules_match_policy:
          type: string
          enum:
          - all
          - any
          description: Whether a product must match all rules or any of them. Defaults
            to `all`.
        sort_order:
          type: string
          enum:
          - manual
          - best_selling
          - price asc
          - price desc
          - available_on desc
          - available_on asc
          - name asc
          - name desc
          description: Default product sort for the storefront listing; a shopper's
            own sort wins. Defaults to `manual`.
        rules:
          type: array
          items:
            "$ref": "#/components/schemas/CollectionRuleParams"
          description: The complete desired rule set. Entries with an `id` update,
            entries without one are created, and existing rules left out are removed.
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomFieldValueParams"
          description: Custom field values, each validated against its definition.
      required:
      - name
    CollectionRuleParams:
      type: object
      properties:
        id:
          type: string
          description: Omit to create a new rule.
          example: crule_abc123
        type:
          type: string
          description: Wire shorthand for the rule kind, from the collection rule
            types endpoint.
          example: tag
        value:
          type: string
          example: summer
        match_policy:
          type: string
          enum:
          - is_equal_to
          - is_not_equal_to
          - contains
          - does_not_contain
          example: contains
    CollectionUpdateParams:
      type: object
      properties:
        name:
          type: string
          example: On Sale
        description:
          type: string
          description: Rich text HTML. Reads come back as this (plain text) plus `description_html`.
        permalink:
          type: string
        position:
          type: integer
          description: 1-based position among the store's collections; the server
            shifts its siblings. The nested products reposition endpoints, unlike
            this, take 0-based indexes.
        meta_title:
          type: string
        meta_description:
          type: string
        meta_keywords:
          type: string
        image_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for the landscape image,
            or null to remove it.
          nullable: true
        square_image_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for the square image, or
            null to remove it.
          nullable: true
        automatic:
          type: boolean
          description: When true, membership is materialized from `rules` instead
            of curated by hand.
        rules_match_policy:
          type: string
          enum:
          - all
          - any
          description: Whether a product must match all rules or any of them. Defaults
            to `all`.
        sort_order:
          type: string
          enum:
          - manual
          - best_selling
          - price asc
          - price desc
          - available_on desc
          - available_on asc
          - name asc
          - name desc
          description: Default product sort for the storefront listing; a shopper's
            own sort wins. Defaults to `manual`.
        rules:
          type: array
          items:
            "$ref": "#/components/schemas/CollectionRuleParams"
          description: The complete desired rule set. Entries with an `id` update,
            entries without one are created, and existing rules left out are removed.
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomFieldValueParams"
          description: Custom field values, each validated against its definition.
    CommissionRateCreateParams:
      type: object
      properties:
        name:
          type: string
          example: Audio sellers
        code:
          type: string
          description: Your own identifier for this rate; unique per store.
          example: audio
          nullable: true
        enabled:
          type: boolean
        position:
          type: integer
          description: Place in the list. Rates resolve top-down and the first whose
            rules match wins, so 1 is tried first. New rates are created at the top;
            send this to move one. A rate with no rules matches every sale, so the
            marketplace default belongs at the bottom.
          example: 1
        kind:
          type: string
          enum:
          - percentage
          - fixed
          description: "`percentage` charges a share of the sale; `fixed` charges
            a flat fee."
          example: percentage
        value:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: A percentage (10 = 10%) or a flat amount, per `kind`.
          example: '12.5'
        tax_inclusive:
          type: boolean
          description: Charge on the price including the customer's VAT. Left off,
            commission is charged on the seller's net revenue, which is the usual
            basis where the fee is taxed as its own supply.
        include_shipping:
          type: boolean
          description: Also charge commission on the seller's delivery revenue. Percentage
            rates only.
        commission_tax_rate:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: VAT on the commission itself, as a fraction rather than a percentage.
            Null lets the store's tax engine answer for the seller's jurisdiction.
          example: '0.21'
          nullable: true
        metadata:
          type: object
          additionalProperties: true
        amounts:
          type: object
          additionalProperties: true
          description: What a flat fee charges, keyed by currency, as decimal strings.
            A sale in a currency with no amount falls to the next matching rate. Replaces
            the whole set.
          example:
            USD: '2.50'
            EUR: '2.00'
        bounds:
          type: object
          additionalProperties: true
          description: 'The floor and cap a percentage charges within, keyed by currency:
            `{ min_amount, max_amount }` decimal strings. A sale in a currency with
            no bounds is charged unbounded. Replaces the whole set.'
          example:
            USD:
              min_amount: '1.00'
              max_amount: '50.00'
        rules:
          type: array
          items:
            "$ref": "#/components/schemas/CommissionRuleDraftParams"
          description: The full targeting; what you send replaces what the rate holds.
      required:
      - name
      - kind
      - value
    CommissionRateUpdateParams:
      type: object
      properties:
        name:
          type: string
          example: Audio sellers
        code:
          type: string
          description: Your own identifier for this rate; unique per store.
          example: audio
          nullable: true
        enabled:
          type: boolean
        position:
          type: integer
          description: Place in the list. Rates resolve top-down and the first whose
            rules match wins, so 1 is tried first. New rates are created at the top;
            send this to move one. A rate with no rules matches every sale, so the
            marketplace default belongs at the bottom.
          example: 1
        kind:
          type: string
          enum:
          - percentage
          - fixed
          description: "`percentage` charges a share of the sale; `fixed` charges
            a flat fee."
          example: percentage
        value:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: A percentage (10 = 10%) or a flat amount, per `kind`.
          example: '12.5'
        tax_inclusive:
          type: boolean
          description: Charge on the price including the customer's VAT. Left off,
            commission is charged on the seller's net revenue, which is the usual
            basis where the fee is taxed as its own supply.
        include_shipping:
          type: boolean
          description: Also charge commission on the seller's delivery revenue. Percentage
            rates only.
        commission_tax_rate:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: VAT on the commission itself, as a fraction rather than a percentage.
            Null lets the store's tax engine answer for the seller's jurisdiction.
          example: '0.21'
          nullable: true
        metadata:
          type: object
          additionalProperties: true
        amounts:
          type: object
          additionalProperties: true
          description: What a flat fee charges, keyed by currency, as decimal strings.
            A sale in a currency with no amount falls to the next matching rate. Replaces
            the whole set.
          example:
            USD: '2.50'
            EUR: '2.00'
        bounds:
          type: object
          additionalProperties: true
          description: 'The floor and cap a percentage charges within, keyed by currency:
            `{ min_amount, max_amount }` decimal strings. A sale in a currency with
            no bounds is charged unbounded. Replaces the whole set.'
          example:
            USD:
              min_amount: '1.00'
              max_amount: '50.00'
        rules:
          type: array
          items:
            "$ref": "#/components/schemas/CommissionRuleDraftParams"
          description: The full targeting; what you send replaces what the rate holds.
    CommissionRuleDraftParams:
      type: object
      properties:
        id:
          type: string
          description: Present for an existing rule; omit to create one.
          nullable: true
        type:
          type: string
          description: A kind from `GET /commission_rates/rule_types`.
          example: seller_rule
        preferences:
          type: object
          additionalProperties: true
          description: Configuration for the kind, per its type's `schema`.
          example:
            seller_ids:
            - sel_a1b2c3
        product_ids:
          type: array
          items:
            type: string
          description: For kinds that name products, which are kept outside preferences.
      required:
      - type
    CompanyAddressCreateParams:
      type: object
      properties:
        first_name:
          type: string
        last_name:
          type: string
        company:
          type: string
        address1:
          type: string
        address2:
          type: string
        city:
          type: string
        postal_code:
          type: string
        phone:
          type: string
        label:
          type: string
        country_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          description: ISO 3166-1 alpha-2 code, such as `US`.
          example: US
        state_code:
          type: string
          description: The state or province abbreviation, such as `NY`.
          example: NY
        state_name:
          type: string
          description: For countries without states in the database.
        default_billing:
          type: boolean
          description: True makes this the default address of that kind, false gives
            the slot up, and leaving it out keeps the current default.
        default_shipping:
          type: boolean
          description: True makes this the default address of that kind, false gives
            the slot up, and leaving it out keeps the current default.
      required:
      - first_name
      - last_name
      - address1
      - city
      - country_code
    CompanyAddressUpdateParams:
      type: object
      properties:
        first_name:
          type: string
        last_name:
          type: string
        company:
          type: string
        address1:
          type: string
        address2:
          type: string
        city:
          type: string
        postal_code:
          type: string
        phone:
          type: string
        label:
          type: string
        country_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          description: ISO 3166-1 alpha-2 code, such as `US`.
          example: US
        state_code:
          type: string
          description: The state or province abbreviation, such as `NY`.
          example: NY
        state_name:
          type: string
          description: For countries without states in the database.
        default_billing:
          type: boolean
          description: True makes this the default address of that kind, false gives
            the slot up, and leaving it out keeps the current default.
        default_shipping:
          type: boolean
          description: True makes this the default address of that kind, false gives
            the slot up, and leaving it out keeps the current default.
    CompanyCreateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        name:
          type: string
          example: Globex Corporation
        kind:
          type: string
          enum:
          - company
          - division
          description: "`company` is a legal entity (may hold tax registrations),
            `division` an organizational unit. Roots must be `company`."
          example: company
        parent_id:
          type: string
          description: The parent node. Omit or null for a root.
          example: comp_86Rf07xd4z
          nullable: true
        po_number_required:
          type: boolean
          description: 'Whether this buyer''s own procurement process demands a PO
            reference on every order: checkout asks for one and refuses to complete
            without it.'
        metadata:
          type: object
          additionalProperties: true
      required:
      - name
    CompanyMembershipCreateParams:
      type: object
      properties:
        customer_id:
          type: string
          description: An existing customer, who becomes a member immediately. Send
            this or `customer_email`.
          example: cus_UkLWZg9DAJ
        customer_email:
          type: string
          description: An existing customer becomes a member immediately; an unknown
            email becomes an invitation, and the response is an invitation instead
            of a membership. Send this or `customer_id`.
          example: buyer@example.com
        metadata:
          type: object
          additionalProperties: true
    CompanyUpdateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        name:
          type: string
          example: Globex Corporation
        kind:
          type: string
          enum:
          - company
          - division
          description: "`company` is a legal entity (may hold tax registrations),
            `division` an organizational unit. Roots must be `company`."
          example: company
        parent_id:
          type: string
          description: The parent node. Omit or null for a root.
          example: comp_86Rf07xd4z
          nullable: true
        po_number_required:
          type: boolean
          description: 'Whether this buyer''s own procurement process demands a PO
            reference on every order: checkout asks for one and refuses to complete
            without it.'
        metadata:
          type: object
          additionalProperties: true
    CustomFieldCreateParams:
      type: object
      properties:
        custom_field_definition_id:
          type: string
          example: cfdef_abc123
        value:
          description: 'A value matching the definition''s `field_type`: a scalar
            for text, number and boolean fields; a list or a hash for JSON fields.'
      required:
      - custom_field_definition_id
      - value
    CustomFieldDefinitionCreateParams:
      type: object
      properties:
        namespace:
          type: string
          description: Defaults to `custom`.
        key:
          type: string
        label:
          type: string
          description: Human-readable name; defaults to the titleized `key`.
        field_type:
          type: string
          description: Custom field type token (`short_text`, `long_text`, `rich_text`,
            `number`, …). An extension type that has no token is named by its registered
            class instead.
          example: short_text
        resource_type:
          type: string
          description: Shorthand of the resource the field attaches to, from the resource
            types endpoint.
          example: product
        storefront_visible:
          type: boolean
          description: When false, the definition is admin-only and never exposed
            in the Store API.
        searchable:
          type: boolean
          description: Include values in storefront product text search. Supported
            for `short_text`, `long_text` and `number` fields; other types are refused.
        sortable:
          type: boolean
          description: Allow storefront product listings to sort by this field (`sort=cf_{namespace}_{key}`).
            Supported for `short_text` and `number` fields; other types are refused.
      required:
      - key
      - field_type
      - resource_type
    CustomFieldDefinitionUpdateParams:
      type: object
      properties:
        namespace:
          type: string
          description: Defaults to `custom`.
        key:
          type: string
        label:
          type: string
          description: Human-readable name; defaults to the titleized `key`.
        field_type:
          type: string
          description: Custom field type token (`short_text`, `long_text`, `rich_text`,
            `number`, …). An extension type that has no token is named by its registered
            class instead.
          example: short_text
        resource_type:
          type: string
          description: Shorthand of the resource the field attaches to, from the resource
            types endpoint.
          example: product
        storefront_visible:
          type: boolean
          description: When false, the definition is admin-only and never exposed
            in the Store API.
        searchable:
          type: boolean
          description: Include values in storefront product text search. Supported
            for `short_text`, `long_text` and `number` fields; other types are refused.
        sortable:
          type: boolean
          description: Allow storefront product listings to sort by this field (`sort=cf_{namespace}_{key}`).
            Supported for `short_text` and `number` fields; other types are refused.
    CustomFieldUpdateParams:
      type: object
      properties:
        value:
          description: 'A value matching the definition''s `field_type`: a scalar
            for text, number and boolean fields; a list or a hash for JSON fields.'
      required:
      - value
    CustomFieldValueParams:
      type: object
      properties:
        id:
          type: string
        custom_field_definition_id:
          type: string
        value:
          description: A scalar for text, number and boolean fields; a list or a hash
            for JSON fields.
    CustomerAddressCreateParams:
      type: object
      properties:
        first_name:
          type: string
        last_name:
          type: string
        company:
          type: string
        address1:
          type: string
        address2:
          type: string
        city:
          type: string
        postal_code:
          type: string
        phone:
          type: string
        label:
          type: string
        country_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          description: ISO 3166-1 alpha-2 code, such as `US`.
          example: US
        state_code:
          type: string
          description: The state or province abbreviation, such as `NY`.
          example: NY
        state_name:
          type: string
          description: For countries without states in the database.
        alternative_phone:
          type: string
        quick_checkout:
          type: boolean
        is_default_billing:
          type: boolean
          description: Makes this the customer's default address of that kind.
        is_default_shipping:
          type: boolean
          description: Makes this the customer's default address of that kind.
      required:
      - first_name
      - last_name
      - address1
      - city
      - country_code
    CustomerAddressUpdateParams:
      type: object
      properties:
        first_name:
          type: string
        last_name:
          type: string
        company:
          type: string
        address1:
          type: string
        address2:
          type: string
        city:
          type: string
        postal_code:
          type: string
        phone:
          type: string
        label:
          type: string
        country_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          description: ISO 3166-1 alpha-2 code, such as `US`.
          example: US
        state_code:
          type: string
          description: The state or province abbreviation, such as `NY`.
          example: NY
        state_name:
          type: string
          description: For countries without states in the database.
        alternative_phone:
          type: string
        quick_checkout:
          type: boolean
        is_default_billing:
          type: boolean
          description: Makes this the customer's default address of that kind.
        is_default_shipping:
          type: boolean
          description: Makes this the customer's default address of that kind.
    CustomerBulkGroupsParams:
      type: object
      properties:
        ids:
          type: array
          items:
            type: string
          example:
          - cus_UkLWZg9DAJ
          - cus_QrLWXg9CAJ
        customer_group_ids:
          type: array
          items:
            type: string
          description: Groups from other stores are ignored.
          example:
          - cg_UkLWZg9DAJ
      required:
      - ids
      - customer_group_ids
    CustomerCreateParams:
      type: object
      properties:
        email:
          type: string
          example: new@example.com
        first_name:
          type: string
        last_name:
          type: string
        phone:
          type: string
        password:
          type: string
          description: 'Optional: a customer created without one claims the account
            through a password reset.'
        password_confirmation:
          type: string
          description: 'Optional: a customer created without one claims the account
            through a password reset.'
        selected_locale:
          type: string
        avatar_signed_id:
          type: string
          description: A `signed_id` from `files.upload()`.
        accepts_email_marketing:
          type: boolean
        internal_note:
          type: string
          description: Rich text HTML. Reads come back as this plus `internal_note_html`.
        metadata:
          type: object
          additionalProperties: true
        tags:
          type: array
          items:
            type: string
        customer_group_ids:
          type: array
          items:
            type: string
          description: Replaces the customer's group membership.
      required:
      - email
    CustomerGroupCreateParams:
      type: object
      properties:
        name:
          type: string
          example: Wholesale
        description:
          type: string
          example: B2B accounts
          nullable: true
        customer_ids:
          type: array
          items:
            type: string
          description: Replaces the group's members.
          example:
          - cus_UkLWZg9DAJ
      required:
      - name
    CustomerGroupUpdateParams:
      type: object
      properties:
        name:
          type: string
          example: Wholesale
        description:
          type: string
          example: B2B accounts
          nullable: true
        customer_ids:
          type: array
          items:
            type: string
          description: Replaces the group's members.
          example:
          - cus_UkLWZg9DAJ
    CustomerStoreCreditCreateParams:
      type: object
      properties:
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '50.00'
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          example: USD
        memo:
          type: string
      required:
      - amount
      - currency
    CustomerStoreCreditUpdateParams:
      type: object
      properties:
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '50.00'
        memo:
          type: string
    CustomerUpdateParams:
      type: object
      properties:
        email:
          type: string
          example: new@example.com
        first_name:
          type: string
        last_name:
          type: string
        phone:
          type: string
        selected_locale:
          type: string
        avatar_signed_id:
          type: string
          description: A `signed_id` from `files.upload()`.
        accepts_email_marketing:
          type: boolean
        internal_note:
          type: string
          description: Rich text HTML. Reads come back as this plus `internal_note_html`.
        metadata:
          type: object
          additionalProperties: true
        tags:
          type: array
          items:
            type: string
        customer_group_ids:
          type: array
          items:
            type: string
          description: Replaces the customer's group membership.
    DataRequestCreateParams:
      type: object
      properties:
        customer_id:
          type: string
        kind:
          type: string
          enum:
          - access
          - erasure
          description: "`access` asks for a copy of the customer's personal data;
            `erasure` asks for it to be erased."
      required:
      - customer_id
      - kind
    DeliveryCreateParams:
      type: object
      properties:
        tracking_number:
          type: string
          description: A carrier tracking number, a freight PRO or container number,
            or a full tracking link. A corrected number resets the carrier status
            to `pending`.
        carrier:
          type: string
          description: Free text; detected from the number's format when omitted.
        service:
          type: string
        tracking_url:
          type: string
      required:
      - tracking_number
    DeliveryMarkDeliveredParams:
      type: object
      properties:
        delivered_at:
          type: string
          format: date-time
          description: When it arrived. Defaults to now.
        notify_customer:
          type: boolean
          description: Whether the customer gets a delivery notification once the
            parcel completes. Defaults to true.
    DeliveryMethodCreateParams:
      type: object
      properties:
        name:
          type: string
          example: Express
        admin_name:
          type: string
          nullable: true
        code:
          type: string
          nullable: true
        fulfillment_provider:
          type: string
          description: Fulfillment provider shorthand (see the fulfillment providers
            endpoint), e.g. `manual`.
          example: manual
        pickup_point_provider:
          type: string
          nullable: true
        rate_provider:
          type: string
          description: Rate provider shorthand (see the rate providers endpoint),
            e.g. `easy_post`. Omit or send null for the built-in provider, which prices
            through the method's calculator.
          nullable: true
        storefront_visible:
          type: boolean
        available_to_sellers:
          type: boolean
          description: 'Marketplace only: whether a seller''s packages may be quoted
            by this method. Off by default, and refused on a method that belongs to
            a seller.'
        tracking_url:
          type: string
          nullable: true
        estimated_transit_business_days_min:
          type: integer
          nullable: true
        estimated_transit_business_days_max:
          type: integer
          nullable: true
        tax_category_id:
          type: string
          description: Prefixed tax category ID (`taxcat_...`), or null to clear.
          nullable: true
        markup_flat:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: Method-level flat handling fee added on top of provider-quoted
            rates.
          nullable: true
        markup_percent:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: Method-level percentage handling fee added on top of provider-quoted
            rates. Ignored for calculator-priced methods.
          nullable: true
        delivery_profile_id:
          type: string
          description: Delivery profile this method belongs to (`fp_...`); defaults
            to the store default profile.
          example: fp_86Rf07xd4z
        delivery_origin_group_id:
          type: string
          description: Origin group offering this method (`og_...`); defaults to the
            zone's group, else the profile's default group.
        delivery_zone_id:
          type: string
          description: Delivery zone narrowing destinations (`dz_...`), or null for
            no restriction. Must belong to the method's profile.
          nullable: true
        stock_location_ids:
          type: array
          items:
            type: string
          description: Pickup locations (`sloc_...`); replaces the full set.
        calculator:
          type: object
          properties:
            type:
              type: string
              example: flat_rate
            preferences:
              type: object
              additionalProperties: true
              example:
                amount: '12.5'
          description: 'How the method prices a shipment: a type from the calculators
            endpoint and its preferences, matching that type''s `schema`.'
        rules:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              type:
                type: string
                description: A rule kind from the delivery method rule types endpoint.
              active:
                type: boolean
              preferences:
                type: object
                additionalProperties: true
              product_ids:
                type: array
                items:
                  type: string
                description: Products an association-backed rule (`excluded_products_rule`)
                  applies to.
          description: 'Eligibility rules. Replaces the full set: omitted rules are
            removed.'
        services:
          type: array
          items:
            "$ref": "#/components/schemas/DeliveryMethodServiceParams"
          description: 'Carrier service rows: which provider services this method
            offers. Replaces the full set: omitted rows are removed; no rows means
            every service the provider returns is offered.'
      required:
      - name
    DeliveryMethodRuleCreateParams:
      type: object
      properties:
        type:
          type: string
          description: A rule kind from the delivery method rule types endpoint.
          example: excluded_products_rule
        active:
          type: boolean
          description: Defaults to true on create.
        preferences:
          type: object
          additionalProperties: true
          description: Values for the rule kind's preference schema.
        product_ids:
          type: array
          items:
            type: string
          description: Products an association-backed rule (`excluded_products_rule`)
            applies to. An empty list clears them.
      required:
      - type
    DeliveryMethodRuleUpdateParams:
      type: object
      properties:
        active:
          type: boolean
          description: Defaults to true on create.
        preferences:
          type: object
          additionalProperties: true
          description: Values for the rule kind's preference schema.
        product_ids:
          type: array
          items:
            type: string
          description: Products an association-backed rule (`excluded_products_rule`)
            applies to. An empty list clears them.
    DeliveryMethodServiceParams:
      type: object
      properties:
        id:
          type: string
          description: Prefixed row ID (`dms_...`) when updating an existing row.
        carrier:
          type: string
          description: Carrier identifier as the provider's API knows it.
          example: UPS
        service:
          type: string
          description: Service identifier as the provider's API knows it.
          example: Ground
        label:
          type: string
          description: Display label shown to customers instead of the carrier-derived
            name.
          nullable: true
        markup_flat:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: Overrides the method-level flat markup for this service.
          nullable: true
        markup_percent:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: Overrides the method-level percentage markup for this service.
          nullable: true
        position:
          type: integer
      required:
      - carrier
      - service
    DeliveryMethodUpdateParams:
      type: object
      properties:
        name:
          type: string
          example: Express
        admin_name:
          type: string
          nullable: true
        code:
          type: string
          nullable: true
        fulfillment_provider:
          type: string
          description: Fulfillment provider shorthand (see the fulfillment providers
            endpoint), e.g. `manual`.
          example: manual
        pickup_point_provider:
          type: string
          nullable: true
        rate_provider:
          type: string
          description: Rate provider shorthand (see the rate providers endpoint),
            e.g. `easy_post`. Omit or send null for the built-in provider, which prices
            through the method's calculator.
          nullable: true
        storefront_visible:
          type: boolean
        available_to_sellers:
          type: boolean
          description: 'Marketplace only: whether a seller''s packages may be quoted
            by this method. Off by default, and refused on a method that belongs to
            a seller.'
        tracking_url:
          type: string
          nullable: true
        estimated_transit_business_days_min:
          type: integer
          nullable: true
        estimated_transit_business_days_max:
          type: integer
          nullable: true
        tax_category_id:
          type: string
          description: Prefixed tax category ID (`taxcat_...`), or null to clear.
          nullable: true
        markup_flat:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: Method-level flat handling fee added on top of provider-quoted
            rates.
          nullable: true
        markup_percent:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: Method-level percentage handling fee added on top of provider-quoted
            rates. Ignored for calculator-priced methods.
          nullable: true
        delivery_profile_id:
          type: string
          description: Delivery profile this method belongs to (`fp_...`); defaults
            to the store default profile.
          example: fp_86Rf07xd4z
        delivery_origin_group_id:
          type: string
          description: Origin group offering this method (`og_...`); defaults to the
            zone's group, else the profile's default group.
        delivery_zone_id:
          type: string
          description: Delivery zone narrowing destinations (`dz_...`), or null for
            no restriction. Must belong to the method's profile.
          nullable: true
        stock_location_ids:
          type: array
          items:
            type: string
          description: Pickup locations (`sloc_...`); replaces the full set.
        calculator:
          type: object
          properties:
            type:
              type: string
              example: flat_rate
            preferences:
              type: object
              additionalProperties: true
              example:
                amount: '12.5'
          description: 'How the method prices a shipment: a type from the calculators
            endpoint and its preferences, matching that type''s `schema`.'
        rules:
          type: array
          items:
            type: object
            properties:
              id:
                type: string
              type:
                type: string
                description: A rule kind from the delivery method rule types endpoint.
              active:
                type: boolean
              preferences:
                type: object
                additionalProperties: true
              product_ids:
                type: array
                items:
                  type: string
                description: Products an association-backed rule (`excluded_products_rule`)
                  applies to.
          description: 'Eligibility rules. Replaces the full set: omitted rules are
            removed.'
        services:
          type: array
          items:
            "$ref": "#/components/schemas/DeliveryMethodServiceParams"
          description: 'Carrier service rows: which provider services this method
            offers. Replaces the full set: omitted rows are removed; no rows means
            every service the provider returns is offered.'
    DeliveryOriginGroupParams:
      type: object
      properties:
        name:
          type: string
          example: EU warehouse
          nullable: true
        position:
          type: integer
        stock_location_ids:
          type: array
          items:
            type: string
          description: Prefixed stock location IDs (`sloc_...`); replaces the full
            set. Empty means every store location.
    DeliveryProfileCreateParams:
      type: object
      properties:
        name:
          type: string
          example: Oversized
        kind:
          type: string
          description: Registered profile kind (`shipping`, `digital`, extension kinds)
            from the kinds endpoint. Read on create only; defaults to shipping.
          example: shipping
        default:
          type: boolean
          description: Promotes this profile to the store default; the previous default
            is demoted.
        position:
          type: integer
        stock_location_ids:
          type: array
          items:
            type: string
          description: Prefixed stock location IDs (`sloc_...`); replaces the full
            set. Empty means every store location.
      required:
      - name
    DeliveryProfileUpdateParams:
      type: object
      properties:
        name:
          type: string
          example: Oversized
        kind:
          type: string
          description: Registered profile kind (`shipping`, `digital`, extension kinds)
            from the kinds endpoint. Read on create only; defaults to shipping.
          example: shipping
        default:
          type: boolean
          description: Promotes this profile to the store default; the previous default
            is demoted.
        position:
          type: integer
        stock_location_ids:
          type: array
          items:
            type: string
          description: Prefixed stock location IDs (`sloc_...`); replaces the full
            set. Empty means every store location.
    DeliveryUpdateParams:
      type: object
      properties:
        tracking_number:
          type: string
          description: A carrier tracking number, a freight PRO or container number,
            or a full tracking link. A corrected number resets the carrier status
            to `pending`.
        carrier:
          type: string
          description: Free text; detected from the number's format when omitted.
        service:
          type: string
        tracking_url:
          type: string
    DeliveryZoneCreateParams:
      type: object
      properties:
        name:
          type: string
          example: US North-East
        description:
          type: string
          nullable: true
        delivery_profile_id:
          type: string
          description: Delivery profile this zone belongs to (`fp_...`); defaults
            to the store default profile.
        delivery_origin_group_id:
          type: string
          description: Origin group this zone belongs to (`og_...`).
        members:
          type: array
          items:
            "$ref": "#/components/schemas/DeliveryZoneMemberParams"
          description: Replaces the zone's full member set atomically.
      required:
      - name
    DeliveryZoneMemberParams:
      type: object
      properties:
        member_type:
          type: string
          enum:
          - country
          - state
          - postal_code
        country_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          example: US
        state_code:
          type: string
          description: A subdivision code or name. Without `country_code` the country
            is inferred when only one country matches.
        postal_code_prefix:
          type: string
        postal_code_from:
          type: string
        postal_code_to:
          type: string
      required:
      - member_type
    DeliveryZoneUpdateParams:
      type: object
      properties:
        name:
          type: string
          example: US North-East
        description:
          type: string
          nullable: true
        delivery_profile_id:
          type: string
          description: Delivery profile this zone belongs to (`fp_...`); defaults
            to the store default profile.
        delivery_origin_group_id:
          type: string
          description: Origin group this zone belongs to (`og_...`).
        members:
          type: array
          items:
            "$ref": "#/components/schemas/DeliveryZoneMemberParams"
          description: Replaces the zone's full member set atomically.
    DigitalAssetCreateParams:
      type: object
      properties:
        signed_id:
          type: string
          description: 'A `signed_id` from `files.upload()` with `visibility: ''private''`.
            On update it replaces the file for everyone who already bought it. A seller''s
            file must be of a content type the marketplace accepts, checked against
            the file''s own signature where it has one.'
        variant_id:
          type: string
          description: On create, defaults to the product's default variant when omitted.
            On update, omitting it keeps the current variant.
        authorized_clicks:
          type: integer
          description: Null means the store's download settings apply.
          nullable: true
        authorized_days:
          type: integer
          description: Null means the store's download settings apply.
          nullable: true
        provider_type:
          type: string
          description: A provider shorthand from the providers endpoint. Omit for
            an uploaded file; a provider-backed asset sends no `signed_id`.
        provider_settings:
          type: object
          additionalProperties: true
          description: Values for the provider's settings schema, keyed by field name.
    DigitalAssetUpdateParams:
      type: object
      properties:
        signed_id:
          type: string
          description: 'A `signed_id` from `files.upload()` with `visibility: ''private''`.
            On update it replaces the file for everyone who already bought it. A seller''s
            file must be of a content type the marketplace accepts, checked against
            the file''s own signature where it has one.'
        variant_id:
          type: string
          description: On create, defaults to the product's default variant when omitted.
            On update, omitting it keeps the current variant.
        authorized_clicks:
          type: integer
          description: Null means the store's download settings apply.
          nullable: true
        authorized_days:
          type: integer
          description: Null means the store's download settings apply.
          nullable: true
        provider_type:
          type: string
          description: A provider shorthand from the providers endpoint. Omit for
            an uploaded file; a provider-backed asset sends no `signed_id`.
        provider_settings:
          type: object
          additionalProperties: true
          description: Values for the provider's settings schema, keyed by field name.
    DiscountCodeApplyParams:
      type: object
      properties:
        code:
          type: string
      required:
      - code
    DiscountCreateParams:
      type: object
      properties:
        label:
          type: string
          example: Customer appeasement
        value:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: An amount in the order currency for a `flat` discount, or a
            percentage for a `percent` one.
          example: '10.00'
        value_type:
          type: string
          enum:
          - flat
          - percent
          description: Defaults to `flat`.
        line_item_id:
          type: string
          description: The line item the discount applies to. Omitted, the value is
            distributed across the line items.
          nullable: true
      required:
      - label
      - value
    DiscountUpdateParams:
      type: object
      properties:
        label:
          type: string
          example: Customer appeasement
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: The new amount of the row, in the order currency.
    EmailTemplateDraftParams:
      type: object
      properties:
        language:
          type: string
          description: A language code, or `any` (the default) for the version every
            language uses.
          example: any
        subject:
          type: string
          example: Your order {{ order.number }} is confirmed
          nullable: true
        body:
          type: string
          example: "<mj-section><mj-column><mj-text>Thanks, {{ order.customer_name
            }}!</mj-text></mj-column></mj-section>"
        lock_version:
          type: integer
          description: The `lock_version` the draft was loaded with, or null when
            there was no draft; a save from an older copy is refused with 409. Omit
            it to save without checking.
          example: 0
          nullable: true
        rebase:
          type: boolean
          description: Marks the draft as based on Spree's current default, after
            reviewing what changed in it.
    EmailTemplatePreviewParams:
      type: object
      properties:
        language:
          type: string
          description: A language code, or `any` (the default) for the version every
            language uses.
          example: any
        subject:
          type: string
          description: An unsaved subject, in place of the current one.
          example: Your order {{ order.number }} is confirmed
          nullable: true
        body:
          type: string
          description: An unsaved body, in place of the current one.
          example: "<mj-section><mj-column><mj-text>Thanks, {{ order.customer_name
            }}!</mj-text></mj-column></mj-section>"
        record_id:
          type: string
          description: The record to build sample data from; the store's latest matching
            record otherwise.
          example: or_m3Rp9wXz
        email_key:
          type: string
          description: For the layout or a partial, the email to show it in.
          example: spree.order_mailer.confirm_email
        branding:
          type: object
          properties:
            accent_color:
              type: string
              nullable: true
            background_color:
              type: string
              nullable: true
            card_color:
              type: string
              nullable: true
            text_color:
              type: string
              nullable: true
            heading_color:
              type: string
              nullable: true
            font:
              type: string
              enum:
              - inter
              - system
              - helvetica
              - georgia
              - roboto
              - lato
              - merriweather
              nullable: true
          description: Unsaved colors and font to preview, named like the store's
            `email_*` settings.
        mailer_logo_signed_id:
          type: string
          description: 'An unsaved email logo: the signed id of an uploaded image,
            or null to preview without one.'
          nullable: true
    EmailTemplateRestoreParams:
      type: object
      properties:
        language:
          type: string
          description: A language code, or `any` (the default) for the version every
            language uses.
          example: any
        lock_version:
          type: integer
          description: The open draft's `lock_version`, or null when there is none;
            checked as when saving.
          nullable: true
    EmailTemplateVersionParams:
      type: object
      properties:
        language:
          type: string
          description: A language code, or `any` (the default) for the version every
            language uses.
          example: any
        lock_version:
          type: integer
          description: The draft's `lock_version` as reviewed. A draft saved since
            is refused with 409.
    ExchangeCancelParams:
      type: object
      properties:
        reason:
          type: string
          description: A note on why the exchange was canceled.
    ExchangeCreateParams:
      type: object
      properties:
        items:
          type: array
          items:
            type: object
            properties:
              fulfillment_item_id:
                type: string
              new_variant_id:
                type: string
              quantity:
                type: integer
            required:
            - fulfillment_item_id
            - new_variant_id
            - quantity
          description: Items coming back, and what goes out in their place.
        stock_location_id:
          type: string
          description: Where the goods come back to.
        reason_id:
          type: string
          description: One of the store's return reasons.
        memo:
          type: string
      required:
      - items
    ExchangeFulfillParams:
      type: object
      properties:
        refund_method:
          type: string
          enum:
          - original_payment
          - store_credit
          description: How a credit is returned when the replacements cost less than
            what came back. Defaults to `store_credit`. A balance the customer owes
            is left for the merchant to collect.
    ExchangeReceiveParams:
      type: object
      properties:
        items:
          type: array
          items:
            type: object
            properties:
              exchange_line_item_id:
                type: string
              quantity:
                type: integer
              resellable:
                type: boolean
                description: Goods that cannot be resold are received but never restocked.
                  Defaults to true.
            required:
            - exchange_line_item_id
            - quantity
          description: What actually arrived. Omit to receive everything as requested
            and resellable.
    ExchangeUpdateParams:
      type: object
      properties:
        stock_location_id:
          type: string
          description: Where the goods come back to.
        reason_id:
          type: string
          description: One of the store's return reasons.
        memo:
          type: string
        metadata:
          type: object
          additionalProperties: true
    ExportCreateParams:
      type: object
      properties:
        type:
          type: string
          description: 'Which dataset to export, as its shorthand: `products`, `orders`,
            `customers`, `product_translations`, `gift_cards`, `coupon_codes`, `newsletter_subscribers`,
            `price_list_prices`, `purchase_orders`, or a type an extension registers.'
          example: products
        record_selection:
          type: string
          enum:
          - filtered
          - all
          description: "`filtered` (the default) keeps `search_params`; `all` ignores
            them and exports every record in scope."
          example: filtered
        results_url:
          type: string
          description: Absolute URL of your admin exports view; the export-done email
            uses it as the download button target. Only honored when it matches one
            of the store's allowed origins.
          example: https://admin.example.com/store_abc/exports
        search_params:
          type: object
          additionalProperties: true
          description: 'A Ransack query, with the predicates the list endpoint accepts.
            A `price_list_prices` export requires `price_list_id_eq` naming a price
            list of the current store, and refuses `record_selection: "all"`.'
          example:
            name_cont: shirt
      required:
      - type
    FeeCreateParams:
      type: object
      properties:
        label:
          type: string
          example: Gift wrap
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '4.00'
        kind:
          anyOf:
          - type: string
            enum:
            - surcharge
            - handling
            - gift_wrap
            - cod
            - payment
            - duty
            - exchange
          - type: string
          description: Defaults to `surcharge`. The values listed are the built-in
            ones; extensions may add more.
          example: gift_wrap
        line_item_id:
          type: string
          description: The line item or fulfillment the fee belongs to. Omitted, the
            fee is order-level.
          nullable: true
        fulfillment_id:
          type: string
          description: The line item or fulfillment the fee belongs to. Omitted, the
            fee is order-level.
          nullable: true
      required:
      - label
      - amount
    FeeUpdateParams:
      type: object
      properties:
        label:
          type: string
          example: Gift wrap
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '4.00'
        kind:
          anyOf:
          - type: string
            enum:
            - surcharge
            - handling
            - gift_wrap
            - cod
            - payment
            - duty
            - exchange
          - type: string
          description: Defaults to `surcharge`. The values listed are the built-in
            ones; extensions may add more.
          example: gift_wrap
    FileUploadCreateParams:
      type: object
      properties:
        filename:
          type: string
          example: registration.pdf
        content_type:
          type: string
          example: application/pdf
        byte_size:
          type: integer
          example: 51234
        checksum:
          type: string
          description: Base64-encoded MD5 digest of the file; the storage service
            checks the bytes against it.
          example: rL0Y20zC+Fzt72VPzMSk2A==
        visibility:
          type: string
          enum:
          - public
          - private
          description: "`public` (the default) for images, videos and CSV files anyone
            may fetch, `private` for any type."
        file:
          type: string
          format: binary
          description: The bytes, for a multipart upload.
      required:
      - filename
      - content_type
    FulfillmentCreateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        stock_location_id:
          type: string
          description: The location the fulfillment ships from. On update, moving
            it re-prices the fulfillment against that location's rates.
        source_fulfillment_id:
          type: string
          description: 'The only fulfillment of this order to move units from, its
            exchange and claim replacements included: how a canceled replacement is
            sent again. Omitted, the customer''s bought units are taken from every
            unshipped fulfillment.'
        tracking:
          type: string
          description: Carrier tracking number, or a full `https://` tracking link,
            which is served back as `tracking_url` unchanged.
        delivery_method_id:
          type: string
          description: Delivery method attached as the selected rate. Defaults to
            the delivery method of the fully drained source fulfillments.
        cost:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: 'Explicit shipping cost, such as the 3PL price. Defaults to
            the summed cost of the fully drained source fulfillments, which keeps
            the order total unchanged. Persists only with `status: shipped`; pending
            fulfillments are re-priced by the rate engine.'
          example: '7.42'
        status:
          type: string
          enum:
          - shipped
          description: Pass `shipped` to register an already-shipped external fulfillment.
        metadata:
          type: object
          additionalProperties: true
        items:
          type: array
          items:
            type: object
            properties:
              item_id:
                type: string
              quantity:
                type: integer
            required:
            - item_id
            - quantity
          description: Line item quantities to fulfill. Omit to fulfill every unit
            not yet shipped.
      required:
      - stock_location_id
    FulfillmentFulfillParams:
      type: object
      properties:
        items:
          type: array
          items:
            type: object
            properties:
              item_id:
                type: string
              quantity:
                type: integer
            required:
            - item_id
            - quantity
          description: Line item quantities to ship. Omit to ship everything the fulfillment
            holds; a subset is split onto a new fulfillment, which is the one that
            ships.
        tracking:
          type: string
          description: Carrier tracking number or a full `https://` tracking link,
            stored on the fulfillment that ships.
        tracking_carrier:
          type: string
          description: Which carrier the number belongs to; detected from the number
            when omitted.
        notify_customer:
          type: boolean
          description: Whether the customer gets the shipment email. Defaults to true;
            pass false to suppress it for this dispatch only.
        force:
          type: boolean
          description: Hand the goods over even though the order is unpaid or holds
            backordered units.
    FulfillmentMarkDeliveredParams:
      type: object
      properties:
        delivered_at:
          type: string
          format: date-time
          description: When it arrived. Defaults to now; return windows run from this
            time.
        notify_customer:
          type: boolean
          description: Whether the customer gets a delivery notification. Defaults
            to true.
    FulfillmentSplitParams:
      type: object
      properties:
        variant_id:
          type: string
          description: The variant being moved out.
        quantity:
          type: integer
        stock_location_id:
          type: string
          description: Origin of the new fulfillment. Defaults to the source fulfillment's
            location.
      required:
      - variant_id
      - quantity
    FulfillmentUpdateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        stock_location_id:
          type: string
          description: The location the fulfillment ships from. On update, moving
            it re-prices the fulfillment against that location's rates.
        tracking:
          type: string
          description: Carrier tracking number, or a full `https://` tracking link,
            which is served back as `tracking_url` unchanged.
        tracking_carrier:
          type: string
          description: 'Which carrier the tracking number belongs to: a slug from
            the tracking carriers endpoint. Left blank, it is detected from the number''s
            format where possible.'
        selected_delivery_rate_id:
          type: string
    GiftCardApplyParams:
      type: object
      properties:
        code:
          type: string
          description: The gift card code; matched case-insensitively.
      required:
      - code
    GiftCardBatchCreateParams:
      type: object
      properties:
        prefix:
          type: string
          description: Lowercased and prepended to every generated code.
          example: WELCOME
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: The amount of each card, greater than zero.
          example: '25.00'
        codes_count:
          type: integer
          description: How many cards to generate. Capped at `gift_card_batch_limit`;
            batches over `gift_card_batch_web_limit` generate in the background.
          example: 100
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          description: ISO 4217 currency code. Defaults to the store currency.
          example: USD
        expires_at:
          type: string
          format: date
          example: '2030-12-31'
          nullable: true
      required:
      - prefix
      - amount
      - codes_count
    GiftCardCreateParams:
      type: object
      properties:
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: Greater than zero.
          example: '25.00'
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          description: ISO 4217 currency code. Defaults to the store currency.
          example: USD
        code:
          type: string
          description: Generated when omitted.
          example: WELCOME50
        expires_at:
          type: string
          format: date
          example: '2030-12-31'
          nullable: true
        customer_id:
          type: string
          description: The customer the card belongs to. Needs the `read_customers`
            permission; null detaches it.
          example: cus_UkLWZg9DAJ
          nullable: true
      required:
      - amount
    GiftCardUpdateParams:
      type: object
      properties:
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: Greater than zero.
          example: '25.00'
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          description: ISO 4217 currency code. Defaults to the store currency.
          example: USD
        code:
          type: string
          description: Generated when omitted.
          example: WELCOME50
        expires_at:
          type: string
          format: date
          example: '2030-12-31'
          nullable: true
        customer_id:
          type: string
          description: The customer the card belongs to. Needs the `read_customers`
            permission; null detaches it.
          example: cus_UkLWZg9DAJ
          nullable: true
    ImportCompleteMappingParams:
      type: object
      properties:
        mappings:
          type: array
          items:
            type: object
            properties:
              schema_field:
                type: string
                description: A schema field name from the import's `schema_fields`.
                example: slug
              file_column:
                type: string
                description: The CSV header to read the field from; null unmaps the
                  field.
                example: Product Handle
                nullable: true
            required:
            - schema_field
          description: Column assignments to apply before processing starts. Omit
            to accept the ones assigned on create.
    ImportCreateParams:
      type: object
      properties:
        type:
          type: string
          description: 'Which dataset to import, as its shorthand: `products`, `customers`,
            `product_translations`, `price_list_prices`, `purchase_orders`, or a type
            an extension registers.'
          example: products
        attachment_signed_id:
          type: string
          description: 'The `signed_id` of the uploaded CSV, from `files.upload()`
            with `visibility: "private"`.'
        delimiter:
          type: string
          enum:
          - ","
          - ";"
          - "|"
          - "\t"
          description: CSV column separator. Defaults to a comma.
          example: ","
        results_url:
          type: string
          description: Absolute URL of your admin imports view; the import-done email
            links back to it with `?import=<id>` appended. Only honored when it matches
            one of the store's allowed origins.
          example: https://admin.example.com/store_abc/settings/imports
        price_list_id:
          type: string
          description: 'For `price_list_prices` imports: the price list the rows are
            merged into. Must belong to the current store; other types ignore it.'
      required:
      - type
      - attachment_signed_id
    IntegrationCreateParams:
      type: object
      properties:
        type:
          type: string
          description: Wire shorthand from the integration types endpoint.
          example: carrier
        active:
          type: boolean
          description: Activating runs the connection check, and a failed check is
            a 422.
        preferences:
          type: object
          additionalProperties: true
          description: Credential values. Secret preferences come back masked, and
            sending a masked value back keeps the stored secret.
      required:
      - type
    IntegrationUpdateParams:
      type: object
      properties:
        active:
          type: boolean
          description: Activating runs the connection check, and a failed check is
            a 422.
        preferences:
          type: object
          additionalProperties: true
          description: Credential values. Secret preferences come back masked, and
            sending a masked value back keeps the stored secret.
    InvitationAcceptParams:
      type: object
      properties:
        password:
          type: string
          description: Creates the account when the invitee has none yet. An existing
            account confirms it is theirs with it, unless the request is already signed
            in as that account.
        password_confirmation:
          type: string
        first_name:
          type: string
        last_name:
          type: string
    InvitationCreateParams:
      type: object
      properties:
        email:
          type: string
        role_id:
          type: string
          description: The role (`role_...`) the invitee gets on accepting.
      required:
      - email
      - role_id
    LineItemCreateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        variant_id:
          type: string
        quantity:
          type: integer
          description: Defaults to 1 when adding an item.
          example: 1
        price:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: 'Negotiated unit price. Stamps the line `price_source: ''manual''`,
            so quantity changes and recalculation never re-price it; an explicit null
            reverts the line to catalog pricing. Omit to leave pricing alone. Draft
            (incomplete) orders only.'
          nullable: true
        options:
          type: object
          additionalProperties: true
      required:
      - variant_id
    LineItemUpdateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        quantity:
          type: integer
          description: Defaults to 1 when adding an item.
          example: 1
        price:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: 'Negotiated unit price. Stamps the line `price_source: ''manual''`,
            so quantity changes and recalculation never re-price it; an explicit null
            reverts the line to catalog pricing. Omit to leave pricing alone. Draft
            (incomplete) orders only.'
          nullable: true
        metadata:
          type: object
          additionalProperties: true
    MaintenanceTaskRunCreateParams:
      type: object
      properties:
        task_name:
          type: string
          description: The task to run, as `task_name` from `GET /upgrade_steps`.
          example: capture_methods
        arguments:
          type: object
          additionalProperties: true
          description: Values for the task's declared parameters, keyed by parameter
            name. A key the task does not declare is rejected.
        dry_run:
          type: boolean
          description: Report what would change without writing. Ignored by tasks
            that do not support a dry run, which run for real.
      required:
      - task_name
    MarketCreateParams:
      type: object
      properties:
        name:
          type: string
          description: Display name, unique within the store.
          example: Europe
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          description: ISO 4217 currency code.
          example: EUR
        default_locale:
          allOf:
          - "$ref": "#/components/schemas/LocaleCode"
          description: Locale used as the market default. Always part of `supported_locales`.
          example: de
        tax_inclusive:
          type: boolean
          description: Whether the prices entered for this market include tax. True
            charges every customer the price as entered, with their tax inside it;
            false adds tax at checkout.
        tax_provider:
          type: string
          description: Shorthand of the tax engine that prices this market, from the
            tax providers endpoint. Null uses the installation default.
          example: internal
          nullable: true
        default:
          type: boolean
          description: Setting true demotes the previous default market of the store.
        position:
          type: integer
          description: Sort order within the store; lower comes first.
        supported_locales:
          type: array
          items:
            "$ref": "#/components/schemas/LocaleCode"
          description: Locales available in this market. The default locale is always
            included.
          example:
          - de
          - en
        country_codes:
          type: array
          items:
            "$ref": "#/components/schemas/CountryCode"
          description: ISO 3166-1 alpha-2 codes of the countries in this market. At
            least one is required.
          example:
          - DE
          - FR
      required:
      - name
      - currency
      - default_locale
      - country_codes
    MarketUpdateParams:
      type: object
      properties:
        name:
          type: string
          description: Display name, unique within the store.
          example: Europe
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          description: ISO 4217 currency code.
          example: EUR
        default_locale:
          allOf:
          - "$ref": "#/components/schemas/LocaleCode"
          description: Locale used as the market default. Always part of `supported_locales`.
          example: de
        tax_inclusive:
          type: boolean
          description: Whether the prices entered for this market include tax. True
            charges every customer the price as entered, with their tax inside it;
            false adds tax at checkout.
        tax_provider:
          type: string
          description: Shorthand of the tax engine that prices this market, from the
            tax providers endpoint. Null uses the installation default.
          example: internal
          nullable: true
        default:
          type: boolean
          description: Setting true demotes the previous default market of the store.
        position:
          type: integer
          description: Sort order within the store; lower comes first.
        supported_locales:
          type: array
          items:
            "$ref": "#/components/schemas/LocaleCode"
          description: Locales available in this market. The default locale is always
            included.
          example:
          - de
          - en
        country_codes:
          type: array
          items:
            "$ref": "#/components/schemas/CountryCode"
          description: ISO 3166-1 alpha-2 codes of the countries in this market. At
            least one is required.
          example:
          - DE
          - FR
    MeUpdateParams:
      type: object
      properties:
        selected_locale:
          type: string
          description: The dashboard display language.
          example: de
        first_name:
          type: string
        last_name:
          type: string
        avatar_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` to set the avatar, or null
            to remove it. Omit it to keep the current photo.
          nullable: true
    MediaCreateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        alt:
          type: string
          example: Front view
          nullable: true
        position:
          type: integer
          example: 1
        media_type:
          type: string
          enum:
          - image
          - video
          - external_video
          description: Defaults to `image`. `video` needs a `signed_id`; `external_video`
            needs an `external_video_url`.
          example: image
        external_video_url:
          type: string
          description: YouTube or Vimeo link. Required when `media_type` is `external_video`.
          nullable: true
        poster_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for a video's poster frame.
        focal_point_x:
          type: number
          description: Where the image is anchored when cropped, from 0 to 1.
          nullable: true
        focal_point_y:
          type: number
          description: Where the image is anchored when cropped, from 0 to 1.
          nullable: true
        attachment:
          type: string
          description: The file itself, sent as multipart form data. JSON clients
            upload first and send `signed_id`.
        url:
          type: string
          description: 'Fetch an image from this URL, in the background. Images only:
            an external video uses `external_video_url`.'
        signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for the media file itself.
        source_media_id:
          type: string
          description: Place a file that is already in the library. The new row shares
            the source file rather than copying it, and takes its own alt, position
            and variant links from here.
        variant_ids:
          type: array
          items:
            type: string
          description: Variants to link this product-level media to. Variants of other
            products are dropped.
    MediaLibraryCreateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        alt:
          type: string
          example: Front view
          nullable: true
        position:
          type: integer
          example: 1
        media_type:
          type: string
          enum:
          - image
          - video
          - external_video
          description: Defaults to `image`. `video` needs a `signed_id`; `external_video`
            needs an `external_video_url`.
          example: image
        external_video_url:
          type: string
          description: YouTube or Vimeo link. Required when `media_type` is `external_video`.
          nullable: true
        poster_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for a video's poster frame.
        focal_point_x:
          type: number
          description: Where the image is anchored when cropped, from 0 to 1.
          nullable: true
        focal_point_y:
          type: number
          description: Where the image is anchored when cropped, from 0 to 1.
          nullable: true
        attachment:
          type: string
          description: The file itself, sent as multipart form data. JSON clients
            upload first and send `signed_id`.
        url:
          type: string
          description: 'Fetch an image from this URL, in the background. Images only:
            an external video uses `external_video_url`.'
        signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for the media file itself.
        source_media_id:
          type: string
          description: Place a file that is already in the library. The new row shares
            the source file rather than copying it, and takes its own alt, position
            and variant links from here.
        variant_ids:
          type: array
          items:
            type: string
          description: Variants to link this product-level media to. Variants of other
            products are dropped.
    MediaLibraryUpdateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        alt:
          type: string
          example: Front view
          nullable: true
        position:
          type: integer
          example: 1
        media_type:
          type: string
          enum:
          - image
          - video
          - external_video
          description: Defaults to `image`. `video` needs a `signed_id`; `external_video`
            needs an `external_video_url`.
          example: image
        external_video_url:
          type: string
          description: YouTube or Vimeo link. Required when `media_type` is `external_video`.
          nullable: true
        poster_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for a video's poster frame.
        focal_point_x:
          type: number
          description: Where the image is anchored when cropped, from 0 to 1.
          nullable: true
        focal_point_y:
          type: number
          description: Where the image is anchored when cropped, from 0 to 1.
          nullable: true
        attachment:
          type: string
          description: The file itself, sent as multipart form data. JSON clients
            upload first and send `signed_id`.
        variant_ids:
          type: array
          items:
            type: string
          description: Variants to link this product-level media to. Variants of other
            products are dropped.
    MediaUpdateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        alt:
          type: string
          example: Front view
          nullable: true
        position:
          type: integer
          example: 1
        media_type:
          type: string
          enum:
          - image
          - video
          - external_video
          description: Defaults to `image`. `video` needs a `signed_id`; `external_video`
            needs an `external_video_url`.
          example: image
        external_video_url:
          type: string
          description: YouTube or Vimeo link. Required when `media_type` is `external_video`.
          nullable: true
        poster_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for a video's poster frame.
        focal_point_x:
          type: number
          description: Where the image is anchored when cropped, from 0 to 1.
          nullable: true
        focal_point_y:
          type: number
          description: Where the image is anchored when cropped, from 0 to 1.
          nullable: true
        attachment:
          type: string
          description: The file itself, sent as multipart form data. JSON clients
            upload first and send `signed_id`.
        variant_ids:
          type: array
          items:
            type: string
          description: Variants to link this product-level media to. Variants of other
            products are dropped.
    OauthApplicationCreateParams:
      type: object
      properties:
        name:
          type: string
          example: Claude
        redirect_uri:
          type: string
          description: Where the authorization server sends the browser back to.
          example: https://claude.ai/api/mcp/auth_callback
      required:
      - name
    OauthApplicationUpdateParams:
      type: object
      properties:
        name:
          type: string
          example: Claude
        redirect_uri:
          type: string
          description: Where the authorization server sends the browser back to.
          example: https://claude.ai/api/mcp/auth_callback
      required:
      - name
    OptionTypeCreateParams:
      type: object
      properties:
        name:
          type: string
          example: color
        label:
          type: string
          example: Color
        position:
          type: integer
        filterable:
          type: boolean
        kind:
          type: string
          enum:
          - dropdown
          - color_swatch
          - buttons
        option_values:
          type: array
          items:
            "$ref": "#/components/schemas/OptionValueParams"
          description: Inline option values. Values left out of the list on update
            are destroyed, so send the full set every time.
      required:
      - name
      - label
    OptionTypeUpdateParams:
      type: object
      properties:
        name:
          type: string
          example: color
        label:
          type: string
          example: Color
        position:
          type: integer
        filterable:
          type: boolean
        kind:
          type: string
          enum:
          - dropdown
          - color_swatch
          - buttons
        option_values:
          type: array
          items:
            "$ref": "#/components/schemas/OptionValueParams"
          description: Inline option values. Values left out of the list on update
            are destroyed, so send the full set every time.
    OptionValueParams:
      type: object
      properties:
        id:
          type: string
          description: Present for existing values. Omit to create a new one.
        name:
          type: string
          example: red
        label:
          type: string
          example: Red
        position:
          type: integer
        color_code:
          type: string
          description: Hex color. Only meaningful when the option type's `kind` is
            `color_swatch`.
          example: "#FF0000"
          nullable: true
        image_signed_id:
          type: string
          description: A `signed_id` from `files.upload()`, or null to remove the
            image.
          nullable: true
    OrderCancelParams:
      type: object
      properties:
        cancel_reason_id:
          type: string
          description: 'Why the order was canceled: the id of one of the store''s
            cancellation reasons.'
        cancel_note:
          type: string
          description: Staff-facing note about the cancellation.
        refund_payments:
          type: boolean
          description: Whether this order's share of a payment shared across a split
            checkout is handed back.
        refund_amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: How much of that share to return. Defaults to all of it; refused
            on an order whose payment is not shared.
        notify_customer:
          type: boolean
          description: Send the order cancellation email after canceling.
    OrderCompleteParams:
      type: object
      properties:
        payment_pending:
          type: boolean
        notify_customer:
          type: boolean
          description: Send the order confirmation email after completion.
    OrderCreateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        email:
          type: string
          example: customer@example.com
        customer_id:
          type: string
          description: Null detaches the customer, leaving a guest order under its
            `email`.
          nullable: true
        use_customer_default_address:
          type: boolean
          description: Copies the saved default billing and shipping addresses onto
            the order. Sent with `company_id`, it takes that company's defaults, inherited
            from its parent nodes when the company holds none of its own; otherwise
            it takes the customer's.
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          example: USD
        market_id:
          type: string
        channel_id:
          type: string
          description: Defaults to the store primary channel when omitted.
        locale:
          allOf:
          - "$ref": "#/components/schemas/LocaleCode"
          example: en-US
        customer_note:
          type: string
          description: Public, customer-visible note.
        internal_note:
          type: string
          description: Staff-only note. Rich text HTML; reads come back as this plus
            `internal_note_html`.
        po_number:
          type: string
          description: The buyer's own purchase-order reference. Searchable alongside
            the order number, and rendered on every order-facing document.
        po_document_signed_id:
          type: string
          description: 'The `signed_id` of the buyer''s purchase order, from `files.upload()`
            with `visibility: ''private''`. Null removes the document the order carries.'
          nullable: true
        shipping_address_id:
          type: string
          description: An existing address from the customer's address book, or from
            the address book of the company the order is for.
        billing_address_id:
          type: string
          description: An existing address from the customer's address book, or from
            the address book of the company the order is for.
        preferred_stock_location_id:
          type: string
          description: Stock location to prefer for fulfillment. Order Routing's built-in
            preferred-location rule ranks it first; routing falls back to the next
            rule when the location can't cover the cart.
        company_id:
          type: string
          description: Makes the order a company purchase, with that company's catalog
            prices and tax treatment. Null makes a draft a plain customer order again.
          nullable: true
        coupon_code:
          type: string
          description: 'Applied non-fatally: an invalid code does not block creation.'
        metadata:
          type: object
          additionalProperties: true
        tags:
          type: array
          items:
            type: string
        shipping_address:
          "$ref": "#/components/schemas/AddressInputParams"
        billing_address:
          "$ref": "#/components/schemas/AddressInputParams"
        use_shipping:
          type: boolean
          description: When true, copies the shipping address to the billing address.
        items:
          type: array
          items:
            type: object
            properties:
              variant_id:
                type: string
              quantity:
                type: integer
                example: 1
              price:
                type: string
                format: decimal
                pattern: "^-?\\d+(\\.\\d+)?$"
                description: 'Negotiated unit price; stamps `price_source: ''manual''`.
                  Null reverts the line to catalog pricing. Draft orders only.'
                nullable: true
              metadata:
                type: object
                additionalProperties: true
            required:
            - variant_id
          description: 'Line items to upsert, keyed by variant. An entry sets that
            variant''s quantity, creating the line item when the order has none; `quantity:
            0` removes it. Variants you do not send are left alone.'
    OrderRoutingRuleCreateParams:
      type: object
      properties:
        type:
          type: string
          description: Wire shorthand for the rule kind, from the order routing rule
            types endpoint.
          example: preferred_location
        active:
          type: boolean
        position:
          type: integer
          description: 1-based priority in the channel's rule list. Omitted on create,
            the rule goes last; a new position reorders the rest of the list around
            it.
        preferences:
          type: object
          additionalProperties: true
          description: Values for the rule kind's preference schema.
      required:
      - type
    OrderRoutingRuleUpdateParams:
      type: object
      properties:
        active:
          type: boolean
        position:
          type: integer
          description: 1-based priority in the channel's rule list. Omitted on create,
            the rule goes last; a new position reorders the rest of the list around
            it.
        preferences:
          type: object
          additionalProperties: true
          description: Values for the rule kind's preference schema.
    OrderUpdateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        email:
          type: string
          example: customer@example.com
        customer_id:
          type: string
          description: Null detaches the customer, leaving a guest order under its
            `email`.
          nullable: true
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          example: USD
        market_id:
          type: string
        channel_id:
          type: string
          description: Defaults to the store primary channel when omitted.
        locale:
          allOf:
          - "$ref": "#/components/schemas/LocaleCode"
          example: en-US
        customer_note:
          type: string
          description: Public, customer-visible note.
        internal_note:
          type: string
          description: Staff-only note. Rich text HTML; reads come back as this plus
            `internal_note_html`.
        po_number:
          type: string
          description: The buyer's own purchase-order reference. Searchable alongside
            the order number, and rendered on every order-facing document.
        po_document_signed_id:
          type: string
          description: 'The `signed_id` of the buyer''s purchase order, from `files.upload()`
            with `visibility: ''private''`. Null removes the document the order carries.'
          nullable: true
        preferred_stock_location_id:
          type: string
          description: Stock location to prefer for fulfillment. Order Routing's built-in
            preferred-location rule ranks it first; routing falls back to the next
            rule when the location can't cover the cart.
        company_id:
          type: string
          description: Makes the order a company purchase, with that company's catalog
            prices and tax treatment. Null makes a draft a plain customer order again.
          nullable: true
        metadata:
          type: object
          additionalProperties: true
        tags:
          type: array
          items:
            type: string
        shipping_address:
          "$ref": "#/components/schemas/AddressInputParams"
        billing_address:
          "$ref": "#/components/schemas/AddressInputParams"
        use_shipping:
          type: boolean
          description: When true, copies the shipping address to the billing address.
        items:
          type: array
          items:
            type: object
            properties:
              variant_id:
                type: string
              quantity:
                type: integer
                example: 1
              price:
                type: string
                format: decimal
                pattern: "^-?\\d+(\\.\\d+)?$"
                description: 'Negotiated unit price; stamps `price_source: ''manual''`.
                  Null reverts the line to catalog pricing. Draft orders only.'
                nullable: true
              metadata:
                type: object
                additionalProperties: true
            required:
            - variant_id
          description: 'Line items to upsert, keyed by variant. An entry sets that
            variant''s quantity, creating the line item when the order has none; `quantity:
            0` removes it. Variants you do not send are left alone.'
    PackageTypeCreateParams:
      type: object
      properties:
        name:
          type: string
          description: Unique within the store.
          example: Euro pallet
        kind:
          type: string
          enum:
          - box
          - envelope
          - carton
          - pallet
          - container
          description: 'What this packaging is: the box parcels ship in, or the carton,
            pallet or container a wholesale order leaves on.'
          example: pallet
        length:
          type: number
          nullable: true
        width:
          type: number
          nullable: true
        height:
          type: number
          nullable: true
        dimensions_unit:
          allOf:
          - "$ref": "#/components/schemas/DimensionUnit"
          description: Unit the three dimensions are in; falls back to the store's
            unit system.
          example: cm
          nullable: true
        weight:
          type: number
          description: The empty package's own weight, added to content weight on
            every quote.
          nullable: true
        max_weight:
          type: number
          description: What the package can hold, not the same as its own weight.
          nullable: true
        weight_unit:
          allOf:
          - "$ref": "#/components/schemas/WeightUnit"
          example: kg
          nullable: true
        default:
          type: boolean
          description: The box every parcel quote is built on. Setting this demotes
            whichever row held it.
        metadata:
          type: object
          additionalProperties: true
      required:
      - name
      - kind
    PackageTypeUpdateParams:
      type: object
      properties:
        name:
          type: string
          description: Unique within the store.
          example: Euro pallet
        kind:
          type: string
          enum:
          - box
          - envelope
          - carton
          - pallet
          - container
          description: 'What this packaging is: the box parcels ship in, or the carton,
            pallet or container a wholesale order leaves on.'
          example: pallet
        length:
          type: number
          nullable: true
        width:
          type: number
          nullable: true
        height:
          type: number
          nullable: true
        dimensions_unit:
          allOf:
          - "$ref": "#/components/schemas/DimensionUnit"
          description: Unit the three dimensions are in; falls back to the store's
            unit system.
          example: cm
          nullable: true
        weight:
          type: number
          description: The empty package's own weight, added to content weight on
            every quote.
          nullable: true
        max_weight:
          type: number
          description: What the package can hold, not the same as its own weight.
          nullable: true
        weight_unit:
          allOf:
          - "$ref": "#/components/schemas/WeightUnit"
          example: kg
          nullable: true
        default:
          type: boolean
          description: The box every parcel quote is built on. Setting this demotes
            whichever row held it.
        metadata:
          type: object
          additionalProperties: true
    PasswordResetParams:
      type: object
      properties:
        password:
          type: string
        password_confirmation:
          type: string
      required:
      - password
      - password_confirmation
    PasswordResetRequestParams:
      type: object
      properties:
        email:
          type: string
          format: email
          example: admin@example.com
        redirect_url:
          type: string
          description: The page the emailed reset link points at, with the reset token
            appended. Honored only on the dashboard origin, for an account that is
            staff of the store; ignored otherwise.
          example: https://admin.your-store.com/reset-password
      required:
      - email
    PaymentCaptureParams:
      type: object
      properties:
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: Captures part of the authorized amount. Defaults to all of
            it.
    PaymentCreateParams:
      type: object
      properties:
        payment_method_id:
          type: string
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: Defaults to the order total left after store credit.
        source_id:
          type: string
          description: A saved payment source of the order's customer (a credit card),
            for an off-session charge. Used only by payment methods that require a
            source.
      required:
      - payment_method_id
    PaymentMethodCreateParams:
      type: object
      properties:
        type:
          type: string
          description: Wire shorthand from the payment method types endpoint.
          example: check
        name:
          type: string
        description:
          type: string
          nullable: true
        active:
          type: boolean
        storefront_visible:
          type: boolean
          description: False keeps the method to the dashboard; true also offers it
            on the storefront.
        capture_method:
          type: string
          enum:
          - checkout
          - on_dispatch
          - manual
          description: When customers are charged for this method. Null inherits the
            store setting.
          nullable: true
        position:
          type: integer
        metadata:
          type: object
          additionalProperties: true
        preferences:
          type: object
          additionalProperties: true
          description: Values for the provider's preference schema, from the payment
            method types endpoint.
      required:
      - type
      - name
    PaymentMethodUpdateParams:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
          nullable: true
        active:
          type: boolean
        storefront_visible:
          type: boolean
          description: False keeps the method to the dashboard; true also offers it
            on the storefront.
        capture_method:
          type: string
          enum:
          - checkout
          - on_dispatch
          - manual
          description: When customers are charged for this method. Null inherits the
            store setting.
          nullable: true
        position:
          type: integer
        metadata:
          type: object
          additionalProperties: true
        preferences:
          type: object
          additionalProperties: true
          description: Values for the provider's preference schema, from the payment
            method types endpoint.
    PolicyCreateParams:
      type: object
      properties:
        name:
          type: string
          example: Wholesale Policy
        slug:
          type: string
          example: wholesale-policy
        body:
          type: string
          example: "<p>Trade orders ship within five working days.</p>"
          nullable: true
      required:
      - name
    PolicyUpdateParams:
      type: object
      properties:
        name:
          type: string
          example: Wholesale Policy
        slug:
          type: string
          example: wholesale-policy
        body:
          type: string
          example: "<p>Trade orders ship within five working days.</p>"
          nullable: true
    PriceAdjustmentTierParams:
      type: object
      properties:
        min_quantity:
          type: integer
          description: Above 1; quantity 1 is the list's own `price_adjustment_percentage`.
          example: 10
        percentage:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: 'Signed: negative discounts, positive marks up.'
          example: "-10.0"
      required:
      - min_quantity
      - percentage
    PriceBulkDestroyParams:
      type: object
      properties:
        ids:
          type: array
          items:
            type: string
          example:
          - price_aBc123
      required:
      - ids
    PriceBulkUpsertParams:
      type: object
      properties:
        prices:
          type: array
          items:
            "$ref": "#/components/schemas/PriceBulkUpsertRowParams"
          description: Send an empty list to change nothing.
      required:
      - prices
    PriceBulkUpsertRowParams:
      type: object
      properties:
        id:
          type: string
          description: 'Present: updates that row. Absent: upserts on `(variant_id,
            currency, price_list_id, min_quantity)`.'
          example: price_aBc123
          nullable: true
        variant_id:
          type: string
          example: variant_xY9
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          example: USD
        price_list_id:
          type: string
          description: Omit or null for a base price.
          example: pl_aBc123
          nullable: true
        min_quantity:
          type: integer
          description: The rung of the variant's ladder. Omit for the bottom rung;
            anything above 1 requires a `price_list_id`. A variant carries at most
            ten rungs on one list per currency.
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '19.99'
          nullable: true
        compare_at_amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '19.99'
          nullable: true
      required:
      - variant_id
      - currency
    PriceCreateParams:
      type: object
      properties:
        variant_id:
          type: string
          example: variant_xY9
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          example: USD
        min_quantity:
          type: integer
          description: The quantity a line must reach for this price to apply. Omit
            for the bottom rung of the ladder. Anything above 1 requires a `price_list_id`.
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '19.99'
          nullable: true
        compare_at_amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '19.99'
          nullable: true
        price_list_id:
          type: string
          description: Omit or null for a base price; a price list for a list override.
          example: pl_aBc123
          nullable: true
      required:
      - variant_id
      - currency
    PriceListCreateParams:
      type: object
      properties:
        name:
          type: string
          example: EU wholesale
        description:
          type: string
          nullable: true
        position:
          type: integer
          example: 1
        starts_at:
          type: string
          format: date-time
          description: 'Pair with `ends_at` to schedule the list: activating a list
            whose start is in the future marks it `scheduled`.'
          example: '2026-06-01T00:00:00Z'
          nullable: true
        ends_at:
          type: string
          format: date-time
          example: '2026-09-01T00:00:00Z'
          nullable: true
        match_policy:
          type: string
          enum:
          - all
          - any
          description: "`all`: every rule must match. `any`: one matching rule is
            enough."
          example: all
        price_adjustment_percentage:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: 'Signed: negative discounts off base prices, positive marks
            up.'
          example: "-15.0"
          nullable: true
        adjust_compare_at:
          type: boolean
        rules:
          type: array
          items:
            "$ref": "#/components/schemas/PriceListRuleParams"
          description: 'The complete rule set: rules are matched by `id` and updated,
            new ones are built, and rules left out are removed.'
        price_adjustment_tiers:
          type: array
          items:
            "$ref": "#/components/schemas/PriceAdjustmentTierParams"
          description: 'Quantity bands on the list''s percentage. The payload is the
            whole ladder: a band left out is removed.'
        prices:
          type: array
          items:
            "$ref": "#/components/schemas/PriceListPriceOverrideParams"
          description: Per-variant price overrides. Each row upserts, so the variants
            it names become part of the list. Curating whole products goes through
            the nested products endpoint instead.
      required:
      - name
    PriceListPriceOverrideParams:
      type: object
      properties:
        id:
          type: string
          description: Updates this price row. Without it, the row upserts on `(variant_id,
            currency, min_quantity)`.
        variant_id:
          type: string
          example: variant_xY9
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          example: USD
        min_quantity:
          type: integer
          description: The rung of the variant's ladder. Omit for the bottom rung.
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '19.99'
          nullable: true
        compare_at_amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '19.99'
          nullable: true
    PriceListRuleParams:
      type: object
      properties:
        id:
          type: string
          description: Present for existing rules. Omit to create a new one.
          nullable: true
        type:
          type: string
          description: Wire shorthand for the rule kind, from the price rule types
            endpoint.
          example: volume_rule
        preferences:
          type: object
          additionalProperties: true
          description: The rule kind's settings, keyed by preference name.
      required:
      - type
    PriceListUpdateParams:
      type: object
      properties:
        name:
          type: string
          example: EU wholesale
        description:
          type: string
          nullable: true
        position:
          type: integer
          example: 1
        starts_at:
          type: string
          format: date-time
          description: 'Pair with `ends_at` to schedule the list: activating a list
            whose start is in the future marks it `scheduled`.'
          example: '2026-06-01T00:00:00Z'
          nullable: true
        ends_at:
          type: string
          format: date-time
          example: '2026-09-01T00:00:00Z'
          nullable: true
        match_policy:
          type: string
          enum:
          - all
          - any
          description: "`all`: every rule must match. `any`: one matching rule is
            enough."
          example: all
        price_adjustment_percentage:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: 'Signed: negative discounts off base prices, positive marks
            up.'
          example: "-15.0"
          nullable: true
        adjust_compare_at:
          type: boolean
        rules:
          type: array
          items:
            "$ref": "#/components/schemas/PriceListRuleParams"
          description: 'The complete rule set: rules are matched by `id` and updated,
            new ones are built, and rules left out are removed.'
        price_adjustment_tiers:
          type: array
          items:
            "$ref": "#/components/schemas/PriceAdjustmentTierParams"
          description: 'Quantity bands on the list''s percentage. The payload is the
            whole ladder: a band left out is removed.'
        prices:
          type: array
          items:
            "$ref": "#/components/schemas/PriceListPriceOverrideParams"
          description: Per-variant price overrides. Each row upserts, so the variants
            it names become part of the list. Curating whole products goes through
            the nested products endpoint instead.
    PriceParams:
      type: object
      properties:
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          example: USD
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: 'A canonical decimal string (`"1234.56"`: period decimal, no
            grouping). The API does not parse localized input.'
          example: '29.99'
        compare_at_amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '39.99'
          nullable: true
      required:
      - currency
      - amount
    PriceUpdateParams:
      type: object
      properties:
        variant_id:
          type: string
          example: variant_xY9
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          example: USD
        min_quantity:
          type: integer
          description: The quantity a line must reach for this price to apply. Omit
            for the bottom rung of the ladder. Anything above 1 requires a `price_list_id`.
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '19.99'
          nullable: true
        compare_at_amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '19.99'
          nullable: true
        price_list_id:
          type: string
          description: Omit or null for a base price; a price list for a list override.
          example: pl_aBc123
          nullable: true
    ProductBulkCategoriesParams:
      type: object
      properties:
        ids:
          type: array
          items:
            type: string
        category_ids:
          type: array
          items:
            type: string
      required:
      - ids
      - category_ids
    ProductBulkChannelsParams:
      type: object
      properties:
        ids:
          type: array
          items:
            type: string
        channel_ids:
          type: array
          items:
            type: string
      required:
      - ids
      - channel_ids
    ProductBulkCollectionsParams:
      type: object
      properties:
        ids:
          type: array
          items:
            type: string
        collection_ids:
          type: array
          items:
            type: string
      required:
      - ids
      - collection_ids
    ProductBulkDestroyParams:
      type: object
      properties:
        ids:
          type: array
          items:
            type: string
          description: Products the caller cannot delete are skipped.
      required:
      - ids
    ProductBulkStatusParams:
      type: object
      properties:
        ids:
          type: array
          items:
            type: string
          example:
          - prod_UkLWZg9DAJ
        status:
          type: string
          enum:
          - draft
          - active
          - archived
          description: Products in review are skipped and counted in `skipped_in_review_count`.
      required:
      - ids
      - status
    ProductCreateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        name:
          type: string
          example: Premium T-Shirt
        description:
          type: string
          description: Rich text HTML. Reads come back as this (plain text) plus `description_html`.
        slug:
          type: string
        status:
          anyOf:
          - type: string
            enum:
            - draft
            - active
            - archived
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        meta_title:
          type: string
        meta_description:
          type: string
        meta_keywords:
          type: string
        tax_category_id:
          type: string
        product_type_id:
          type: string
          description: The product type this product is created from (`pt_...`). Its
            option types and categories seed onto the product and its custom field
            definitions drive the product form. Editing the type later never rewrites
            existing products.
          nullable: true
        delivery_profile_id:
          type: string
          description: The delivery profile deciding how this product ships (`fp_...`);
            null falls back to the store default.
          nullable: true
        promotionable:
          type: boolean
        tags:
          type: array
          items:
            type: string
          example:
          - eco
          - sale
        category_ids:
          type: array
          items:
            type: string
        collection_ids:
          type: array
          items:
            type: string
          description: Manual collections this product belongs to. Automatic collections
            are kept as they are, since their rules decide membership.
        metadata:
          type: object
          additionalProperties: true
        prices:
          type: array
          items:
            "$ref": "#/components/schemas/PriceParams"
          description: 'Shorthand for a simple (no-options) product: per-currency
            prices that forward to the product''s sole variant. For products with
            options, set prices per variant under `variants` instead. Don''t pass
            both.'
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomFieldValueParams"
          description: Custom field values, each validated against its definition.
        media:
          type: array
          items:
            "$ref": "#/components/schemas/ProductMediaParams"
          description: Media written with the product. Entries with `id` update an
            existing asset; entries with `signed_id` attach a fresh upload; an external
            video needs only its URL.
        digital_assets:
          type: array
          items:
            "$ref": "#/components/schemas/ProductDigitalAssetParams"
          description: Downloadable files written with the product. Each entry carries
            a `signed_id` (an upload to private storage) or a `provider_type` (a provider-backed
            asset), and attaches to the default variant unless `variant_id` is given.
            An `id` updates that asset in place, so replaying the list does not duplicate
            it; removal uses the nested digital assets endpoint.
        product_publications:
          type: array
          items:
            "$ref": "#/components/schemas/ProductPublicationParams"
        variants:
          type: array
          items:
            "$ref": "#/components/schemas/ProductVariantParams"
          description: Every purchasable attribute (sku, prices, stock, weight, dimensions)
            lives on variants. An entry without `options` upserts onto the default
            variant of a simple product; pass `id` to update an existing variant.
      required:
      - name
    ProductDigitalAssetParams:
      type: object
      properties:
        id:
          type: string
        signed_id:
          type: string
        variant_id:
          type: string
        provider_type:
          type: string
          description: A provider shorthand from the digital asset providers endpoint.
        provider_settings:
          type: object
          additionalProperties: true
          description: Values for the provider's settings schema, keyed by field name.
        authorized_clicks:
          type: integer
          description: Null means the store's download settings apply.
          nullable: true
        authorized_days:
          type: integer
          description: Null means the store's download settings apply.
          nullable: true
    ProductMediaParams:
      type: object
      properties:
        id:
          type: string
        signed_id:
          type: string
          description: A `signed_id` from `files.upload()`.
        source_media_id:
          type: string
          description: Copies an asset from the media library.
        alt:
          type: string
          example: Front view
          nullable: true
        position:
          type: integer
          example: 1
        media_type:
          type: string
          enum:
          - image
          - video
          - external_video
          description: Defaults to `image`. `video` needs a `signed_id`; `external_video`
            needs an `external_video_url`.
          example: image
        external_video_url:
          type: string
          description: YouTube or Vimeo link. Required when `media_type` is `external_video`.
          nullable: true
        poster_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for a video's poster frame.
        focal_point_x:
          type: number
          description: Where the image is anchored when cropped, from 0 to 1.
          nullable: true
        focal_point_y:
          type: number
          description: Where the image is anchored when cropped, from 0 to 1.
          nullable: true
        variant_ids:
          type: array
          items:
            type: string
          description: Replaces the variants this media is linked to. An empty list
            clears them.
    ProductMembershipParams:
      type: object
      properties:
        product_ids:
          type: array
          items:
            type: string
          description: Products from other stores, or ones the caller cannot see,
            are ignored.
          example:
          - prod_abc123
      required:
      - product_ids
    ProductMembershipRepositionParams:
      type: object
      properties:
        new_position:
          type: integer
          description: 0-based index among the parent's products.
          example: 0
      required:
      - new_position
    ProductPublicationParams:
      type: object
      properties:
        id:
          type: string
        channel_id:
          type: string
        published_at:
          type: string
          format: date-time
          nullable: true
        unpublished_at:
          type: string
          format: date-time
          nullable: true
    ProductRejectParams:
      type: object
      properties:
        reason:
          type: string
          description: Why the submission was turned down. Sent back to the seller.
    ProductTypeCreateParams:
      type: object
      properties:
        name:
          type: string
          example: Hoodie
        delivery_profile_id:
          type: string
          description: Delivery profile stamped onto products created with this type.
            Null leaves new products on the store default profile.
          example: fp_86Rf07xd4z
          nullable: true
        option_type_ids:
          type: array
          items:
            type: string
          description: Option types seeded onto products that get this type. Use apply
            to products to backfill existing ones.
        category_ids:
          type: array
          items:
            type: string
          description: Categories seeded onto products that get this type. Categories
            from other stores are ignored.
        custom_field_definitions:
          type: array
          items:
            "$ref": "#/components/schemas/ProductTypeCustomFieldDefinitionParams"
          description: The custom field definitions the product form shows. Definitions
            not listed are removed from the type.
      required:
      - name
    ProductTypeCustomFieldDefinitionParams:
      type: object
      properties:
        id:
          type: string
          description: The custom field definition.
          example: cfdef_abc123
        required:
          type: boolean
        sort_order:
          type: integer
      required:
      - id
    ProductTypeUpdateParams:
      type: object
      properties:
        name:
          type: string
          example: Hoodie
        delivery_profile_id:
          type: string
          description: Delivery profile stamped onto products created with this type.
            Null leaves new products on the store default profile.
          example: fp_86Rf07xd4z
          nullable: true
        option_type_ids:
          type: array
          items:
            type: string
          description: Option types seeded onto products that get this type. Use apply
            to products to backfill existing ones.
        category_ids:
          type: array
          items:
            type: string
          description: Categories seeded onto products that get this type. Categories
            from other stores are ignored.
        custom_field_definitions:
          type: array
          items:
            "$ref": "#/components/schemas/ProductTypeCustomFieldDefinitionParams"
          description: The custom field definitions the product form shows. Definitions
            not listed are removed from the type.
    ProductUpdateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        name:
          type: string
          example: Premium T-Shirt
        description:
          type: string
          description: Rich text HTML. Reads come back as this (plain text) plus `description_html`.
        slug:
          type: string
        status:
          anyOf:
          - type: string
            enum:
            - draft
            - active
            - archived
          - type: string
          description: The values listed are the built-in ones; extensions may add
            more.
        meta_title:
          type: string
        meta_description:
          type: string
        meta_keywords:
          type: string
        tax_category_id:
          type: string
        product_type_id:
          type: string
          description: The product type this product is created from (`pt_...`). Its
            option types and categories seed onto the product and its custom field
            definitions drive the product form. Editing the type later never rewrites
            existing products.
          nullable: true
        delivery_profile_id:
          type: string
          description: The delivery profile deciding how this product ships (`fp_...`);
            null falls back to the store default.
          nullable: true
        promotionable:
          type: boolean
        tags:
          type: array
          items:
            type: string
          example:
          - eco
          - sale
        category_ids:
          type: array
          items:
            type: string
        collection_ids:
          type: array
          items:
            type: string
          description: Manual collections this product belongs to. Automatic collections
            are kept as they are, since their rules decide membership.
        metadata:
          type: object
          additionalProperties: true
        prices:
          type: array
          items:
            "$ref": "#/components/schemas/PriceParams"
          description: 'Shorthand for a simple (no-options) product: per-currency
            prices that forward to the product''s sole variant. For products with
            options, set prices per variant under `variants` instead. Don''t pass
            both.'
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomFieldValueParams"
          description: Custom field values, each validated against its definition.
        media:
          type: array
          items:
            "$ref": "#/components/schemas/ProductMediaParams"
          description: Media written with the product. Entries with `id` update an
            existing asset; entries with `signed_id` attach a fresh upload; an external
            video needs only its URL.
        digital_assets:
          type: array
          items:
            "$ref": "#/components/schemas/ProductDigitalAssetParams"
          description: Downloadable files written with the product. Each entry carries
            a `signed_id` (an upload to private storage) or a `provider_type` (a provider-backed
            asset), and attaches to the default variant unless `variant_id` is given.
            An `id` updates that asset in place, so replaying the list does not duplicate
            it; removal uses the nested digital assets endpoint.
        product_publications:
          type: array
          items:
            "$ref": "#/components/schemas/ProductPublicationParams"
        variants:
          type: array
          items:
            "$ref": "#/components/schemas/ProductVariantParams"
          description: Every purchasable attribute (sku, prices, stock, weight, dimensions)
            lives on variants. An entry without `options` upserts onto the default
            variant of a simple product; pass `id` to update an existing variant.
    ProductVariantParams:
      allOf:
      - "$ref": "#/components/schemas/VariantParams"
      - type: object
        properties:
          id:
            type: string
    PromotionActionCalculatorParams:
      type: object
      properties:
        type:
          type: string
          description: The calculator kind, from `GET /promotion_actions/calculators`.
            Changing it swaps the calculator.
          example: flat_percent_item_total
        preferences:
          type: object
          additionalProperties: true
          description: Values for the calculator's settings, such as `amount` or `flat_percent`.
    PromotionActionCreateParams:
      type: object
      properties:
        type:
          type: string
          description: The action kind, from `GET /promotion_actions/types`.
          example: free_shipping
        preferences:
          type: object
          additionalProperties: true
          description: Values for the action kind's settings schema, from `GET /promotion_actions/types`.
        calculator:
          allOf:
          - "$ref": "#/components/schemas/PromotionActionCalculatorParams"
          description: For adjustment actions.
        line_items:
          type: array
          items:
            "$ref": "#/components/schemas/PromotionActionLineItemParams"
          description: 'For `create_line_items`: the variants to add and their quantities.
            Variants left out are removed.'
      required:
      - type
    PromotionActionDraftParams:
      type: object
      properties:
        id:
          type: string
        type:
          type: string
          description: The action kind, from `GET /promotion_actions/types`.
          example: free_shipping
        preferences:
          type: object
          additionalProperties: true
          description: Values for the action kind's settings schema, from `GET /promotion_actions/types`.
        calculator:
          allOf:
          - "$ref": "#/components/schemas/PromotionActionCalculatorParams"
          description: For adjustment actions.
        line_items:
          type: array
          items:
            "$ref": "#/components/schemas/PromotionActionLineItemParams"
          description: 'For `create_line_items`: the variants to add and their quantities.
            Variants left out are removed.'
      required:
      - type
    PromotionActionLineItemParams:
      type: object
      properties:
        variant_id:
          type: string
        quantity:
          type: integer
      required:
      - variant_id
      - quantity
    PromotionActionUpdateParams:
      type: object
      properties:
        preferences:
          type: object
          additionalProperties: true
          description: Values for the action kind's settings schema, from `GET /promotion_actions/types`.
        calculator:
          allOf:
          - "$ref": "#/components/schemas/PromotionActionCalculatorParams"
          description: For adjustment actions.
        line_items:
          type: array
          items:
            "$ref": "#/components/schemas/PromotionActionLineItemParams"
          description: 'For `create_line_items`: the variants to add and their quantities.
            Variants left out are removed.'
    PromotionCreateParams:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
          nullable: true
        code:
          type: string
          description: Required for single-code coupon promotions. Ignored when `multi_codes`
            is true.
          nullable: true
        path:
          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
          description: "`coupon_code` needs a code (or `multi_codes`); `automatic`
            applies without one."
        multi_codes:
          type: boolean
          description: Generates `number_of_codes` codes starting with `code_prefix`.
        number_of_codes:
          type: integer
          nullable: true
        code_prefix:
          type: string
          nullable: true
        promotion_category_id:
          type: string
          nullable: true
        rules:
          type: array
          items:
            "$ref": "#/components/schemas/PromotionRuleDraftParams"
          description: 'The rules the promotion should have: entries with `id` update,
            entries without are created, and rules left out are removed.'
        actions:
          type: array
          items:
            "$ref": "#/components/schemas/PromotionActionDraftParams"
          description: The actions the promotion should have, matched the same way
            as `rules`.
      required:
      - name
    PromotionRuleCreateParams:
      type: object
      properties:
        type:
          type: string
          description: The rule kind, from `GET /promotion_rules/types`.
          example: currency
        preferences:
          type: object
          additionalProperties: true
          description: Values for the rule kind's settings schema, from `GET /promotion_rules/types`.
        product_ids:
          type: array
          items:
            type: string
          description: For the `product` rule.
        category_ids:
          type: array
          items:
            type: string
          description: For the `category` rule.
        customer_ids:
          type: array
          items:
            type: string
          description: 'For the `user` rule: the customers who qualify.'
      required:
      - type
    PromotionRuleDraftParams:
      type: object
      properties:
        id:
          type: string
        type:
          type: string
          description: The rule kind, from `GET /promotion_rules/types`.
          example: currency
        preferences:
          type: object
          additionalProperties: true
          description: Values for the rule kind's settings schema, from `GET /promotion_rules/types`.
        product_ids:
          type: array
          items:
            type: string
          description: For the `product` rule.
        category_ids:
          type: array
          items:
            type: string
          description: For the `category` rule.
        customer_ids:
          type: array
          items:
            type: string
          description: 'For the `user` rule: the customers who qualify.'
      required:
      - type
    PromotionRuleUpdateParams:
      type: object
      properties:
        preferences:
          type: object
          additionalProperties: true
          description: Values for the rule kind's settings schema, from `GET /promotion_rules/types`.
        product_ids:
          type: array
          items:
            type: string
          description: For the `product` rule.
        category_ids:
          type: array
          items:
            type: string
          description: For the `category` rule.
        customer_ids:
          type: array
          items:
            type: string
          description: 'For the `user` rule: the customers who qualify.'
    PromotionUpdateParams:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
          nullable: true
        code:
          type: string
          description: Required for single-code coupon promotions. Ignored when `multi_codes`
            is true.
          nullable: true
        path:
          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
          description: "`coupon_code` needs a code (or `multi_codes`); `automatic`
            applies without one."
        multi_codes:
          type: boolean
          description: Generates `number_of_codes` codes starting with `code_prefix`.
        number_of_codes:
          type: integer
          nullable: true
        code_prefix:
          type: string
          nullable: true
        promotion_category_id:
          type: string
          nullable: true
        rules:
          type: array
          items:
            "$ref": "#/components/schemas/PromotionRuleDraftParams"
          description: 'The rules the promotion should have: entries with `id` update,
            entries without are created, and rules left out are removed.'
        actions:
          type: array
          items:
            "$ref": "#/components/schemas/PromotionActionDraftParams"
          description: The actions the promotion should have, matched the same way
            as `rules`.
    PurchaseOrderCancelParams:
      type: object
      properties:
        reason:
          type: string
          description: Appended to the order's notes.
          example: Supplier went under
    PurchaseOrderCreateParams:
      type: object
      properties:
        supplier_id:
          type: string
          example: sup_1234567890
        destination_location_id:
          type: string
          example: sloc_1234567890
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          description: Defaults to the store's currency; set it for a foreign-currency
            order.
          example: USD
          nullable: true
        expected_at:
          type: string
          format: date
          description: The day the supplier promised. `null` clears it.
          example: '2026-10-01'
          nullable: true
        cancel_by:
          type: string
          format: date
          description: The day after which the goods are no longer wanted. `null`
            clears it.
          nullable: true
        reference:
          type: string
          description: The supplier's own order number. `null` clears it.
          nullable: true
        notes:
          type: string
          nullable: true
        items:
          type: array
          items:
            "$ref": "#/components/schemas/PurchaseOrderItemParams"
          description: Sending the list replaces whatever the order currently holds.
        metadata:
          type: object
          additionalProperties: true
          nullable: true
      required:
      - supplier_id
      - destination_location_id
    PurchaseOrderItemParams:
      type: object
      properties:
        variant_id:
          type: string
          example: variant_1234567890
        quantity_ordered:
          type: integer
          example: 100
        unit_cost:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: What the merchant agreed to pay per unit.
          example: '12.50'
      required:
      - variant_id
      - quantity_ordered
      - unit_cost
    PurchaseOrderUpdateParams:
      type: object
      properties:
        supplier_id:
          type: string
          example: sup_1234567890
        destination_location_id:
          type: string
          example: sloc_1234567890
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          description: Defaults to the store's currency; set it for a foreign-currency
            order.
          example: USD
          nullable: true
        expected_at:
          type: string
          format: date
          description: The day the supplier promised. `null` clears it.
          example: '2026-10-01'
          nullable: true
        cancel_by:
          type: string
          format: date
          description: The day after which the goods are no longer wanted. `null`
            clears it.
          nullable: true
        reference:
          type: string
          description: The supplier's own order number. `null` clears it.
          nullable: true
        notes:
          type: string
          nullable: true
        items:
          type: array
          items:
            "$ref": "#/components/schemas/PurchaseOrderItemParams"
          description: Sending the list replaces whatever the order currently holds.
        metadata:
          type: object
          additionalProperties: true
          nullable: true
    ReasonCreateParams:
      type: object
      properties:
        name:
          type: string
        active:
          type: boolean
          description: Whether the reason is offered on new records.
      required:
      - name
    ReasonUpdateParams:
      type: object
      properties:
        name:
          type: string
        active:
          type: boolean
          description: Whether the reason is offered on new records.
    ReceivableCloseParams:
      type: object
      properties:
        reason:
          type: string
          description: Why the balance is not coming.
          nullable: true
    RefundCreateParams:
      type: object
      properties:
        payment_id:
          type: string
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
        refund_reason_id:
          type: string
          description: Defaults to the store's first refund reason.
      required:
      - payment_id
      - amount
    ReportingQueryParams:
      type: object
      properties:
        metrics:
          type: array
          items:
            type: string
          description: Registered metric names, from the reporting schema endpoint.
        dimensions:
          type: array
          items: {}
          description: 'Up to 2 dimensions to break the metrics down by. Each is a
            dimension name, or `{ name, grain, include_empty }`: `grain` (`hour`,
            `day`, `week`, `month`) buckets a time dimension, and `include_empty`
            lists members with no matching rows where the schema entry supports it.'
        filters:
          type: array
          items:
            type: object
            properties:
              dimension:
                type: string
              op:
                type: string
                enum:
                - eq
                - in
              value:
                description: One value for `eq`, a list for `in`.
            required:
            - dimension
            - op
            - value
          description: Narrows the rows by dimension value.
        metric_filters:
          type: array
          items:
            type: object
            properties:
              metric:
                type: string
              op:
                type: string
                enum:
                - eq
                - gt
                - gte
                - lt
                - lte
              value:
                type: number
            required:
            - metric
            - op
            - value
          description: Filters on an aggregate, such as `units_sold = 0`. Narrows
            the rows only; the totals stay the period's real figure. The metric must
            also appear in `metrics`, and cannot be a derived one.
        time_range:
          type: object
          properties:
            preset:
              type: string
            since:
              type: string
            until:
              type: string
          description: A named preset (`last_month`, `week_to_date`, any `last_<n>_<days|weeks|months>`),
            or ISO 8601 dates or times in `since` and `until` (a bare date covers
            the store's whole day). Defaults to the last 30 days, in the store's time
            zone.
        compare:
          type: string
          enum:
          - previous_period
          - previous_year
        sort:
          type: string
          description: A metric name; prefix it with `-` to sort descending.
        limit:
          type: integer
          description: At most 1000.
        currency:
          "$ref": "#/components/schemas/CurrencyCode"
      required:
      - metrics
    ReturnCancelParams:
      type: object
      properties:
        reason:
          type: string
          description: A note on why the return was canceled.
    ReturnCreateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        items:
          type: array
          items:
            type: object
            properties:
              fulfillment_item_id:
                type: string
              quantity:
                type: integer
            required:
            - fulfillment_item_id
            - quantity
          description: Fulfilled units coming back, and how many of each.
        stock_location_id:
          type: string
          description: Where the goods come back to. Defaults to the location that
            shipped them.
        reason_id:
          type: string
          description: One of the store's return reasons.
        memo:
          type: string
      required:
      - items
    ReturnReceiveParams:
      type: object
      properties:
        items:
          type: array
          items:
            type: object
            properties:
              return_line_item_id:
                type: string
              quantity:
                type: integer
              resellable:
                type: boolean
                description: Goods that cannot be resold are received but never restocked.
                  Defaults to true.
            required:
            - return_line_item_id
            - quantity
          description: What actually arrived. Omit to receive everything as requested
            and resellable; send rows for a partial or damaged receipt.
    ReturnRefundParams:
      type: object
      properties:
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: Defaults to the value of what was actually received.
        refund_method:
          type: string
          enum:
          - original_payment
          - store_credit
          description: "`store_credit` issues credit immediately; `original_payment`
            (the default) refunds through the gateway that took the money."
    ReturnUpdateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        stock_location_id:
          type: string
          description: Where the goods come back to. Defaults to the location that
            shipped them.
        reason_id:
          type: string
          description: One of the store's return reasons.
        memo:
          type: string
        metadata:
          type: object
          additionalProperties: true
    RoleCreateParams:
      type: object
      properties:
        name:
          type: string
          description: Unique role name, the machine identifier shown capitalized
            in the dashboard.
          example: order_manager
        description:
          type: string
          example: Handles daily orders
          nullable: true
        permissions:
          type: array
          items:
            type: string
          description: Permission keys (`read_orders`, `write_products`, ...) from
            the permissions endpoint. You can only grant keys you hold yourself.
          example:
          - write_orders
          - read_customers
      required:
      - name
    RoleUpdateParams:
      type: object
      properties:
        name:
          type: string
          description: Unique role name, the machine identifier shown capitalized
            in the dashboard.
          example: order_manager
        description:
          type: string
          example: Handles daily orders
          nullable: true
        permissions:
          type: array
          items:
            type: string
          description: Permission keys (`read_orders`, `write_products`, ...) from
            the permissions endpoint. You can only grant keys you hold yourself.
          example:
          - write_orders
          - read_customers
    SavedReportCreateParams:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
          nullable: true
        query:
          type: object
          additionalProperties: true
          description: A reporting query, validated against the reporting registry
            on save.
      required:
      - name
      - query
    SavedReportUpdateParams:
      type: object
      properties:
        name:
          type: string
        description:
          type: string
          nullable: true
        query:
          type: object
          additionalProperties: true
          description: A reporting query, validated against the reporting registry
            on save.
    SellerAddressParams:
      type: object
      properties:
        first_name:
          type: string
        last_name:
          type: string
        company:
          type: string
        address1:
          type: string
        address2:
          type: string
        city:
          type: string
        postal_code:
          type: string
        phone:
          type: string
        label:
          type: string
        country_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          description: ISO 3166-1 alpha-2 code, such as `US`.
          example: US
        state_code:
          type: string
          description: The state or province abbreviation, such as `NY`.
          example: NY
        state_name:
          type: string
          description: For countries without states in the database.
    SellerApproveParams:
      type: object
      properties:
        override_requirements:
          type: boolean
          description: 'Admits a seller whose onboarding checklist is unfinished:
            the operator''s deliberate exception, which the `seller.approved` event
            records along with what was outstanding. Also admits a `pending` or `invited`
            seller who never started onboarding, which is refused without it.'
    SellerCreateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        name:
          type: string
          example: Northwind Books
        slug:
          type: string
          description: URL-safe slug, derived from the name when omitted.
          example: northwind-books
        contact_email:
          type: string
          example: hi@northwind.example
          nullable: true
        billing_email:
          type: string
          example: billing@northwind.example
          nullable: true
        about:
          type: string
          description: 'Sanitized HTML: the seller''s public description.'
          example: "<p>Independent bookshop.</p>"
          nullable: true
        logo_signed_id:
          type: string
          description: A `signed_id` from the files upload endpoint to set the image,
            `null` to remove it, or omit the key to leave it untouched. The same applies
            to `square_logo_signed_id` and `cover_photo_signed_id`.
          nullable: true
        square_logo_signed_id:
          type: string
          nullable: true
        cover_photo_signed_id:
          type: string
          nullable: true
        tax_remittance:
          type: string
          enum:
          - seller
          - platform
          example: seller
        payouts_schedule_interval:
          type: string
          enum:
          - daily
          - weekly
          - biweekly
          - monthly
          - manual
          nullable: true
        minimum_payout_amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '25.0'
          nullable: true
        holiday_mode_until:
          type: string
          format: date-time
          description: 'Set while the seller is away: the catalog stays but stops
            selling.'
          nullable: true
        legal_name:
          type: string
          nullable: true
        registration_number:
          type: string
          nullable: true
        metadata:
          type: object
          additionalProperties: true
        billing_address:
          allOf:
          - "$ref": "#/components/schemas/SellerAddressParams"
          description: 'The seller''s own billing address, written inline. There is
            no `billing_address_id`: an address belongs to whoever it was created
            for, so it is never referenced by id.'
        returns_address:
          allOf:
          - "$ref": "#/components/schemas/SellerAddressParams"
          description: 'Where customers send returns, written inline. It is the address
            of the seller''s returns stock location, so it updates that location,
            or creates one for a seller who has none. Names and `label` are ignored:
            a location has none.'
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomFieldValueParams"
          description: Custom field values, each validated against its definition.
      required:
      - name
    SellerInvitationCreateParams:
      type: object
      properties:
        email:
          type: string
          example: teammate@example.com
      required:
      - email
    SellerInviteParams:
      type: object
      properties:
        email:
          type: string
          example: seller@example.com
        role_id:
          type: string
          description: A role this seller owns; defaults to the seller's own admin
            role.
          example: role_UkLWZg9DAJ
          nullable: true
      required:
      - email
    SellerPayoutCompleteParams:
      type: object
      properties:
        reference:
          type: string
          description: The provider's own id for the settlement, when one made it.
          example: TRF-8842
    SellerRejectParams:
      type: object
      properties:
        reason:
          type: string
          example: Incomplete paperwork
    SellerReopenOnboardingParams:
      type: object
      properties:
        note:
          type: string
          description: What the seller has to fix.
    SellerRequirementCreateParams:
      type: object
      properties:
        type:
          type: string
          description: The kind, from the seller requirement types endpoint.
          example: document
        name:
          type: string
          description: What the seller sees. Required for kinds that can be added
            more than once, since the wording is the only thing telling them apart.
            Left blank on the others, the kind names itself.
          example: Business registration
        description:
          type: string
          description: Instructions shown to the seller.
          example: A copy of your certificate of incorporation.
        position:
          type: integer
          description: Place in the checklist.
          example: 1
        active:
          type: boolean
          example: true
        required:
          type: boolean
          description: Whether this blocks approval. Off means recommended.
          example: true
        preferences:
          type: object
          additionalProperties: true
          description: Configuration for this kind, per its type's `schema`.
          example:
            accepted_content_types:
            - application/pdf
        metadata:
          type: object
          additionalProperties: true
        custom_field_definition_ids:
          type: array
          items:
            type: string
          description: Custom field definitions this requirement asks the seller to
            fill in (`required_custom_fields` kind).
      required:
      - type
    SellerRequirementReviewParams:
      type: object
      properties:
        review_note:
          type: string
          description: Kept with the decision. On a rejection it is the reason sent
            back to the seller.
    SellerRequirementUpdateParams:
      type: object
      properties:
        name:
          type: string
          description: What the seller sees. Required for kinds that can be added
            more than once, since the wording is the only thing telling them apart.
            Left blank on the others, the kind names itself.
          example: Business registration
        description:
          type: string
          description: Instructions shown to the seller.
          example: A copy of your certificate of incorporation.
        position:
          type: integer
          description: Place in the checklist.
          example: 1
        active:
          type: boolean
          example: true
        required:
          type: boolean
          description: Whether this blocks approval. Off means recommended.
          example: true
        preferences:
          type: object
          additionalProperties: true
          description: Configuration for this kind, per its type's `schema`.
          example:
            accepted_content_types:
            - application/pdf
        metadata:
          type: object
          additionalProperties: true
        custom_field_definition_ids:
          type: array
          items:
            type: string
          description: Custom field definitions this requirement asks the seller to
            fill in (`required_custom_fields` kind).
    SellerRequirementWaiveParams:
      type: object
      properties:
        requirement_id:
          type: string
          description: The requirement the seller is excused from.
          example: selreq_UkLWZg9DAJ
        review_note:
          type: string
          description: Why the seller is excused. Kept with the decision.
      required:
      - requirement_id
    SellerSuspendParams:
      type: object
      properties:
        reason:
          type: string
          example: Counterfeit goods
    SellerUpdateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        name:
          type: string
          example: Northwind Books
        slug:
          type: string
          description: URL-safe slug, derived from the name when omitted.
          example: northwind-books
        contact_email:
          type: string
          example: hi@northwind.example
          nullable: true
        billing_email:
          type: string
          example: billing@northwind.example
          nullable: true
        about:
          type: string
          description: 'Sanitized HTML: the seller''s public description.'
          example: "<p>Independent bookshop.</p>"
          nullable: true
        logo_signed_id:
          type: string
          description: A `signed_id` from the files upload endpoint to set the image,
            `null` to remove it, or omit the key to leave it untouched. The same applies
            to `square_logo_signed_id` and `cover_photo_signed_id`.
          nullable: true
        square_logo_signed_id:
          type: string
          nullable: true
        cover_photo_signed_id:
          type: string
          nullable: true
        tax_remittance:
          type: string
          enum:
          - seller
          - platform
          example: seller
        payouts_schedule_interval:
          type: string
          enum:
          - daily
          - weekly
          - biweekly
          - monthly
          - manual
          nullable: true
        minimum_payout_amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          example: '25.0'
          nullable: true
        holiday_mode_until:
          type: string
          format: date-time
          description: 'Set while the seller is away: the catalog stays but stops
            selling.'
          nullable: true
        legal_name:
          type: string
          nullable: true
        registration_number:
          type: string
          nullable: true
        metadata:
          type: object
          additionalProperties: true
        billing_address:
          allOf:
          - "$ref": "#/components/schemas/SellerAddressParams"
          description: 'The seller''s own billing address, written inline. There is
            no `billing_address_id`: an address belongs to whoever it was created
            for, so it is never referenced by id.'
        returns_address:
          allOf:
          - "$ref": "#/components/schemas/SellerAddressParams"
          description: 'Where customers send returns, written inline. It is the address
            of the seller''s returns stock location, so it updates that location,
            or creates one for a seller who has none. Names and `label` are ignored:
            a location has none.'
        custom_fields:
          type: array
          items:
            "$ref": "#/components/schemas/CustomFieldValueParams"
          description: Custom field values, each validated against its definition.
    SetupParams:
      type: object
      properties:
        setup_token:
          type: string
          description: The one-time token from the install output.
        email:
          type: string
          format: email
          example: owner@example.com
        password:
          type: string
        password_confirmation:
          type: string
        first_name:
          type: string
          example: Olivia
        last_name:
          type: string
          example: Owner
        store_name:
          type: string
          example: My Store
        country_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          description: ISO 3166-1 alpha-2 country the store sells from. It determines
            the default market, the warehouse, the delivery zones and the currency.
          example: US
        locale:
          allOf:
          - "$ref": "#/components/schemas/LocaleCode"
          description: Storefront locale. Defaults to the country's own language.
          example: en
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          description: 'ISO 4217 currency. Defaults to the country''s own currency:
            pass one only when the store prices in something else.'
          example: USD
        sample_data:
          type: boolean
          description: Load the demo catalog, customers and orders in the background
            once the admin account exists. The load takes minutes, so the response
            does not wait for it.
      required:
      - setup_token
      - email
      - password
      - country_code
    ShippingLabelCreateParams:
      type: object
      properties:
        file_signed_id:
          type: string
          description: A `signed_id` from `files.upload()`. Its presence records a
            label bought elsewhere instead of buying one; without it the body is ignored
            and the label is bought through the carrier.
        tracking_number:
          type: string
          description: The number printed on an uploaded label. Required with `file_signed_id`.
        carrier:
          type: string
          description: Free text; a forwarder's name is as valid as a carrier slug.
            Detected from the number when omitted.
        service:
          type: string
          description: Carrier service the label was bought at.
        cost:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: What the merchant paid the carrier. Accounting data only; it
            never touches the order's shipping charge.
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          description: Currency of the cost.
        file_format:
          type: string
          enum:
          - pdf
          - png
          - zpl
          description: Taken from the file when omitted.
        tracking_url:
          type: string
          description: Tracking page for the consignment the label mints.
    StockLevelBulkUpsertParams:
      type: object
      properties:
        stock_levels:
          type: array
          items:
            "$ref": "#/components/schemas/StockLevelBulkUpsertRowParams"
          description: Send an empty list to change nothing.
      required:
      - stock_levels
    StockLevelBulkUpsertRowParams:
      type: object
      properties:
        variant_id:
          type: string
          example: variant_xY9
        stock_location_id:
          type: string
          example: sloc_aBc
        count_on_hand:
          type: integer
          description: The absolute level the external system reports.
          example: 42
          nullable: true
        adjustment:
          type: integer
          description: A relative change, for feeds that report movements rather than
            levels. Each row needs `count_on_hand` or `adjustment`.
          example: -3
          nullable: true
        backorderable:
          type: boolean
          nullable: true
        reason:
          type: string
          description: Labels the movement in the stock history. Defaults to "Inventory
            feed".
          example: received
          nullable: true
      required:
      - variant_id
      - stock_location_id
    StockLevelParams:
      type: object
      properties:
        stock_location_id:
          type: string
          description: The location holding the stock (`sloc_...`).
        count_on_hand:
          type: integer
          description: 'Units physically at the location, not units available to sell:
            stock promised to placed orders counts until it ships. Sent as the count
            the shelf should end at; the API records the difference as an adjustment
            in the stock history.'
        backorderable:
          type: boolean
          description: Whether this location sells the variant beyond what it holds.
      required:
      - stock_location_id
      - count_on_hand
    StockLevelUpdateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        count_on_hand:
          type: integer
          description: 'The count the shelf should end at: a whole number of zero
            or more. The API records the difference as an `adjusted` movement, so
            the correction appears in the stock history.'
        adjustment:
          type: integer
          description: A signed change to the shelf instead of a target count, applied
            to the count the API holds at that moment and recorded the same way. Cannot
            be sent together with `count_on_hand`.
        backorderable:
          type: boolean
          description: Whether this location sells the variant beyond what it holds.
        reason:
          type: string
          description: Labels the correction in the stock history. Defaults to "Manual
            adjustment".
        metadata:
          type: object
          additionalProperties: true
    StockLocationCreateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        name:
          type: string
          example: Brooklyn warehouse
        admin_name:
          type: string
          description: Internal name shown only in the admin.
          nullable: true
        active:
          type: boolean
        default:
          type: boolean
          description: Setting to true demotes the previous default.
        kind:
          anyOf:
          - type: string
            enum:
            - warehouse
            - store
            - fulfillment_center
          - type: string
          description: Categorizes the location. The values listed are the built-in
            ones; extensions may add more.
          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_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          description: ISO-3166 alpha-2 country code.
          example: US
          nullable: true
        state_code:
          type: string
          description: State or province abbreviation, resolved against the selected
            country's states.
          example: NY
          nullable: true
        state_name:
          type: string
          description: Free-text state for countries that don't have a states list.
          nullable: true
        pickup_enabled:
          type: boolean
        pickup_stock_policy:
          type: string
          enum:
          - local
          - any
          description: "`local` collects only items at this location; `any` lets items
            transfer in from other locations (ship-to-store)."
        pickup_ready_in_minutes:
          type: integer
          nullable: true
        returns_enabled:
          type: boolean
          description: Whether customers may send returns to this location.
        pickup_instructions:
          type: string
          nullable: true
      required:
      - name
    StockLocationUpdateParams:
      type: object
      properties:
        external_references:
          type: object
          additionalProperties: true
          description: 'Identities the record has in external systems, keyed by system:
            the same `{ system: external_id }` map the Admin API renders, so what
            you read can be sent straight back. Systems you do not name keep the reference
            they have. A list of `{ system, external_id }` entries is accepted too.'
        name:
          type: string
          example: Brooklyn warehouse
        admin_name:
          type: string
          description: Internal name shown only in the admin.
          nullable: true
        active:
          type: boolean
        default:
          type: boolean
          description: Setting to true demotes the previous default.
        kind:
          anyOf:
          - type: string
            enum:
            - warehouse
            - store
            - fulfillment_center
          - type: string
          description: Categorizes the location. The values listed are the built-in
            ones; extensions may add more.
          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_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          description: ISO-3166 alpha-2 country code.
          example: US
          nullable: true
        state_code:
          type: string
          description: State or province abbreviation, resolved against the selected
            country's states.
          example: NY
          nullable: true
        state_name:
          type: string
          description: Free-text state for countries that don't have a states list.
          nullable: true
        pickup_enabled:
          type: boolean
        pickup_stock_policy:
          type: string
          enum:
          - local
          - any
          description: "`local` collects only items at this location; `any` lets items
            transfer in from other locations (ship-to-store)."
        pickup_ready_in_minutes:
          type: integer
          nullable: true
        returns_enabled:
          type: boolean
          description: Whether customers may send returns to this location.
        pickup_instructions:
          type: string
          nullable: true
    StockReceiptCreateParams:
      type: object
      properties:
        reference:
          type: string
          description: The supplier's delivery note, or the carrier's reference.
          example: DN-4471
          nullable: true
        received_at:
          type: string
          format: date-time
          description: When the goods were counted in. Defaults to now.
          nullable: true
        notes:
          type: string
          nullable: true
        items:
          type: array
          items:
            "$ref": "#/components/schemas/StockReceiptItemParams"
          description: 'Omit to book in everything still outstanding, intact. Naming
            lines, even none, records exactly what the dock counted: `quantity_accepted`
            reaches the shelf; `quantity_rejected` is refused, recorded with a `rejection_reason`
            and never stocked.'
    StockReceiptItemParams:
      type: object
      properties:
        id:
          type: string
          description: The purchase order or transfer line.
        quantity_accepted:
          type: integer
          example: 58
        quantity_rejected:
          type: integer
          example: 2
        rejection_reason:
          type: string
          enum:
          - damaged
          - wrong_item
          - expired
          - other
          example: damaged
          nullable: true
        notes:
          type: string
          nullable: true
      required:
      - id
    StockTransferCancelParams:
      type: object
      properties:
        on_in_transit:
          type: string
          enum:
          - restock
          - write_off
          description: 'Required once the units have left the source: either they
            come back (`restock`) or they are written off as lost (`write_off`).'
        reason:
          type: string
          description: Recorded against the written-off lines.
          nullable: true
    StockTransferCreateParams:
      type: object
      properties:
        source_location_id:
          type: string
          example: sloc_1234567890
        destination_location_id:
          type: string
          example: sloc_1234567890
        reference:
          type: string
          description: The merchant's own label for the trip. `null` clears it.
          nullable: true
        notes:
          type: string
          nullable: true
        items:
          type: array
          items:
            "$ref": "#/components/schemas/StockTransferItemParams"
          description: A draft may open empty and gain lines as the merchant packs.
            Sending the list replaces whatever the draft currently holds.
        metadata:
          type: object
          additionalProperties: true
          nullable: true
      required:
      - source_location_id
      - destination_location_id
    StockTransferItemParams:
      type: object
      properties:
        variant_id:
          type: string
          example: variant_1234567890
        quantity_shipped:
          type: integer
          example: 10
      required:
      - variant_id
      - quantity_shipped
    StockTransferMarkInTransitParams:
      type: object
      properties:
        force:
          type: boolean
          description: Ship even if it drives the source below zero.
    StockTransferUpdateParams:
      type: object
      properties:
        source_location_id:
          type: string
          example: sloc_1234567890
        destination_location_id:
          type: string
          example: sloc_1234567890
        reference:
          type: string
          description: The merchant's own label for the trip. `null` clears it.
          nullable: true
        notes:
          type: string
          nullable: true
        items:
          type: array
          items:
            "$ref": "#/components/schemas/StockTransferItemParams"
          description: A draft may open empty and gain lines as the merchant packs.
            Sending the list replaces whatever the draft currently holds.
        metadata:
          type: object
          additionalProperties: true
          nullable: true
    StoreCreditApplyParams:
      type: object
      properties:
        amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: Defaults to the customer's available store credit, up to the
            order total.
    StoreUpdateParams:
      type: object
      properties:
        name:
          type: string
          example: My Store
        seo_title:
          type: string
          description: The storefront's default page title, in the store's default
            language. Translate it through the translations endpoints.
          nullable: true
        meta_description:
          type: string
          description: The storefront's default meta description, in the store's default
            language.
          nullable: true
        admin_locale:
          allOf:
          - "$ref": "#/components/schemas/LocaleCode"
          description: The language the dashboard opens in for every staff member;
            null lets each use their own.
          example: en
          nullable: true
        timezone:
          allOf:
          - "$ref": "#/components/schemas/TimeZone"
          example: Europe/Berlin
        weight_unit:
          "$ref": "#/components/schemas/WeightUnit"
        unit_system:
          type: string
          enum:
          - metric
          - imperial
        storefront_access:
          type: string
          enum:
          - public
          - prices_hidden
          - login_required
          description: The store-wide default for what anonymous visitors can see.
            Channels fall back to it when they don't set their own.
        storefront_url:
          type: string
          description: The storefront's public URL, the base for links in customer
            emails. Saving it also completes the storefront setup task.
          nullable: true
        guest_checkout:
          type: boolean
          description: The store-wide default for guest checkout. Channels fall back
            to it.
        always_include_confirm_step:
          type: boolean
          description: Always show a confirmation step in checkout, even when no payment
            method requires one.
        company_field_enabled:
          type: boolean
          description: Shows a company field on address forms.
        address_requires_company:
          type: boolean
          description: Makes a company name mandatory on addresses.
        address_requires_phone:
          type: boolean
          description: Makes a phone number mandatory on customer addresses.
        capture_method:
          type: string
          enum:
          - checkout
          - on_dispatch
          - manual
          description: The store-wide default for when a customer is charged rather
            than only authorized. A payment method's own setting wins when set.
        track_inventory_levels:
          type: boolean
          description: Counts on-hand quantities. Off means everything is treated
            as always available.
        stock_reservations_enabled:
          type: boolean
          description: Holds stock for shoppers while they check out, so the same
            item can't be sold twice.
        low_stock_threshold:
          type: integer
          description: On-hand units at or below which a tracked variant counts as
            low stock on the home screen; 0 turns the warning off.
        tax_using_ship_address:
          type: boolean
          description: Calculates tax from the shipping address. When false, tax is
            calculated from the billing address.
        track_price_history:
          type: boolean
          description: Records price changes for the EU Omnibus lowest-price-in-30-days
            display.
        show_products_without_price:
          type: boolean
          description: Whether products with no price in the shopper's currency still
            appear in listings.
        disable_sku_validation:
          type: boolean
          description: Lets more than one variant share the same SKU.
        order_routing_strategy:
          type: string
          description: The store-wide order routing strategy shorthand. Channels fall
            back to it.
        pricing_provider:
          type: string
          description: 'Where prices come from: a registered provider key, or `internal`.'
        inventory_provider:
          type: string
          description: 'Where stock levels come from: a registered provider key, or
            `internal`.'
        pricing_provider_failure_policy:
          type: string
          enum:
          - fallback
          - strict
          description: "`strict` refuses to price when the provider cannot answer;
            `fallback` uses the catalog."
        inventory_provider_failure_policy:
          type: string
          enum:
          - fallback
          - strict
          description: "`fallback` sells on the local stock snapshot when the provider
            cannot answer; `strict` refuses."
        payout_provider:
          type: string
          description: 'Blank means the built-in provider: the marketplace settles
            by hand.'
        default_payouts_schedule_interval:
          type: string
          enum:
          - daily
          - weekly
          - biweekly
          - monthly
          - manual
        default_minimum_payout_amount:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: In the store's currency.
          example: '50.00'
        auto_approve_sellers:
          type: boolean
          description: Admits a seller as soon as they finish onboarding, with no
            operator review.
        auto_approve_seller_products:
          type: boolean
          description: Puts a seller product on sale the moment it is submitted, with
            no review.
        seller_digital_assets_enabled:
          type: boolean
          description: Lets sellers attach downloadable files to their own products.
        seller_digital_asset_content_types:
          type: array
          items:
            type: string
          description: The content types a seller's file may have, checked against
            the file's own signature where it has one. An entry names one type or,
            with `*` as the subtype, a whole family. The operator's own uploads are
            not restricted.
          example:
          - application/pdf
          - application/zip
        review_seller_digital_asset_changes:
          type: boolean
          description: Sends a seller product already on sale back to review when
            the seller adds or replaces a file on it.
        send_seller_transactional_emails:
          type: boolean
          description: When false, transactional seller emails (approval, payouts
            and so on) are not sent.
        default_commission_tax_rate:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: Tax charged on commission as a fraction (`"0.23"` is 23%),
            when neither the commission rate nor the tax provider names one.
          example: '0.23'
        document_number_format:
          type: string
          description: 'How document numbers are produced: `sequential` or `random`.
            Applies to every numbered document.'
          example: sequential
        order_number_prefix:
          type: string
          description: 'Leads every order number. Uppercase letters, digits, dashes
            and # only.'
          example: R
        order_number_suffix:
          type: string
          description: 'Ends every order number. Uppercase letters, digits, dashes
            and # only.'
        order_number_sequence_start:
          type: integer
          description: The first sequential order number. Only applies before the
            store's first order.
        limit_digital_download_count:
          type: boolean
          description: Whether a digital download link stops working after a number
            of clicks.
        digital_asset_authorized_clicks:
          type: integer
          description: How many clicks a download link allows, unless the file sets
            its own.
        limit_digital_download_days:
          type: boolean
          description: Whether a digital download link expires after a number of days.
        digital_asset_authorized_days:
          type: integer
          description: How many days a download link stays valid, unless the file
            sets its own.
        mail_from_address:
          type: string
          description: Sender address of every transactional email.
        customer_support_email:
          type: string
          description: Customer-facing reply-to address shown in the storefront and
            email footers.
          nullable: true
        new_order_notifications_email:
          type: string
          description: Recipient of "new order placed" staff notifications.
          nullable: true
        send_consumer_transactional_emails:
          type: boolean
          description: When false, transactional customer emails (order confirmation
            and so on) are not sent.
        email_accent_color:
          type: string
          description: Customer email buttons and links, as `#RRGGBB`. Blank keeps
            the outlined buttons emails ship with.
          nullable: true
        email_background_color:
          type: string
          description: Customer email page background, as `#RRGGBB`.
          nullable: true
        email_card_color:
          type: string
          description: Customer email card behind the content, as `#RRGGBB`.
          nullable: true
        email_text_color:
          type: string
          description: Customer email body text, as `#RRGGBB`.
          nullable: true
        email_heading_color:
          type: string
          description: Customer email headings and emphasized text, as `#RRGGBB`.
          nullable: true
        email_font:
          type: string
          description: 'Customer email font: `inter`, `system`, `helvetica`, `georgia`,
            `roboto`, `lato` or `merriweather`.'
          example: inter
          nullable: true
        logo_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for the store logo, or
            null to remove it.
          nullable: true
        mailer_logo_signed_id:
          type: string
          description: A `signed_id` from `files.upload()` for the logo in transactional
            emails, or null to remove it.
          nullable: true
    SupplierCreateParams:
      type: object
      properties:
        name:
          type: string
          example: Northwind Trading
        contact_name:
          type: string
          example: Dana Okafor
          nullable: true
        email:
          type: string
          example: sales@northwind.test
          nullable: true
        phone:
          type: string
          example: 555-0100
          nullable: true
        notes:
          type: string
          nullable: true
        address1:
          type: string
          example: 1 Warehouse Way
          nullable: true
        address2:
          type: string
          nullable: true
        city:
          type: string
          example: Brooklyn
          nullable: true
        state_name:
          type: string
          nullable: true
        state_code:
          type: string
          example: NY
          nullable: true
        country_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          example: US
          nullable: true
        postal_code:
          type: string
          example: '11201'
          nullable: true
        metadata:
          type: object
          additionalProperties: true
          nullable: true
      required:
      - name
    SupplierUpdateParams:
      type: object
      properties:
        name:
          type: string
          example: Northwind Trading
        contact_name:
          type: string
          example: Dana Okafor
          nullable: true
        email:
          type: string
          example: sales@northwind.test
          nullable: true
        phone:
          type: string
          example: 555-0100
          nullable: true
        notes:
          type: string
          nullable: true
        address1:
          type: string
          example: 1 Warehouse Way
          nullable: true
        address2:
          type: string
          nullable: true
        city:
          type: string
          example: Brooklyn
          nullable: true
        state_name:
          type: string
          nullable: true
        state_code:
          type: string
          example: NY
          nullable: true
        country_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          example: US
          nullable: true
        postal_code:
          type: string
          example: '11201'
          nullable: true
        metadata:
          type: object
          additionalProperties: true
          nullable: true
    TaxCategoryCreateParams:
      type: object
      properties:
        name:
          type: string
        tax_code:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        is_default:
          type: boolean
      required:
      - name
    TaxCategoryUpdateParams:
      type: object
      properties:
        name:
          type: string
        tax_code:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        is_default:
          type: boolean
    TaxExemptionCertificateCreateParams:
      type: object
      properties:
        certificate_number:
          type: string
          example: DE-RESALE-7
        tax_exemption_reason_id:
          type: string
          description: One of the store's active tax exemption reasons. The tax provider
            receives its `code`.
        issuing_authority:
          type: string
          example: Finanzamt Berlin
          nullable: true
        issued_at:
          type: string
          format: date-time
          nullable: true
        expires_at:
          type: string
          format: date-time
          nullable: true
        country_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          description: Where the certificate holds. Omit it and `state_code` for one
            valid everywhere.
          nullable: true
        state_code:
          type: string
          nullable: true
        document_signed_id:
          type: string
          description: 'A `signed_id` from `files.upload()` with `visibility: ''private''`.'
        metadata:
          type: object
          additionalProperties: true
      required:
      - certificate_number
      - tax_exemption_reason_id
    TaxExemptionCertificateUpdateParams:
      type: object
      properties:
        certificate_number:
          type: string
          example: DE-RESALE-7
        tax_exemption_reason_id:
          type: string
          description: One of the store's active tax exemption reasons. The tax provider
            receives its `code`.
        issuing_authority:
          type: string
          example: Finanzamt Berlin
          nullable: true
        issued_at:
          type: string
          format: date-time
          nullable: true
        expires_at:
          type: string
          format: date-time
          nullable: true
        country_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          description: Where the certificate holds. Omit it and `state_code` for one
            valid everywhere.
          nullable: true
        state_code:
          type: string
          nullable: true
        document_signed_id:
          type: string
          description: 'A `signed_id` from `files.upload()` with `visibility: ''private''`.'
        metadata:
          type: object
          additionalProperties: true
    TaxExemptionReasonCreateParams:
      type: object
      properties:
        name:
          type: string
        active:
          type: boolean
          description: Whether the reason is offered on new records.
        code:
          type: string
          description: What the tax provider receives for every certificate holding
            this reason — for Avalara, an entity use code such as `G`. Saved in capitals.
            Changing it changes what those certificates send from then on.
          example: RESALE
        metadata:
          type: object
          additionalProperties: true
      required:
      - name
      - code
    TaxExemptionReasonUpdateParams:
      type: object
      properties:
        name:
          type: string
        active:
          type: boolean
          description: Whether the reason is offered on new records.
        code:
          type: string
          description: What the tax provider receives for every certificate holding
            this reason — for Avalara, an entity use code such as `G`. Saved in capitals.
            Changing it changes what those certificates send from then on.
          example: RESALE
        metadata:
          type: object
          additionalProperties: true
    TaxIdentifierCreateParams:
      type: object
      properties:
        kind:
          type: string
          description: 'The registration the number belongs to, such as `eu_vat` or
            `gb_vat`. Any kind is accepted; one with a registered validator is checked
            by it. Built-in: `eu_vat`. Extensions may register more.'
          example: gb_vat
        value:
          type: string
          example: GB123456789
      required:
      - kind
      - value
    TaxIdentifierUpdateParams:
      type: object
      properties:
        kind:
          type: string
          description: 'The registration the number belongs to, such as `eu_vat` or
            `gb_vat`. Any kind is accepted; one with a registered validator is checked
            by it. Built-in: `eu_vat`. Extensions may register more.'
          example: gb_vat
        value:
          type: string
          example: GB123456789
    TaxRateCreateParams:
      type: object
      properties:
        name:
          type: string
          description: Customer-facing rate name.
          example: VAT
        rate:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: The rate as a fraction. Send this or `rate_percent`.
          example: '0.19'
        rate_percent:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: The rate as a percentage.
          example: '19'
        show_rate_in_label:
          type: boolean
        tax_category_id:
          type: string
        country_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          description: ISO country code. A rate naming no country taxes everywhere.
          example: DE
          nullable: true
        state_code:
          type: string
          description: State abbreviation within that country.
          example: CA
          nullable: true
        metadata:
          type: object
          additionalProperties: true
      required:
      - name
      - tax_category_id
    TaxRateUpdateParams:
      type: object
      properties:
        name:
          type: string
          description: Customer-facing rate name.
          example: VAT
        rate:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: The rate as a fraction. Send this or `rate_percent`.
          example: '0.19'
        rate_percent:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          description: The rate as a percentage.
          example: '19'
        show_rate_in_label:
          type: boolean
        tax_category_id:
          type: string
        country_code:
          allOf:
          - "$ref": "#/components/schemas/CountryCode"
          description: ISO country code. A rate naming no country taxes everywhere.
          example: DE
          nullable: true
        state_code:
          type: string
          description: State abbreviation within that country.
          example: CA
          nullable: true
        metadata:
          type: object
          additionalProperties: true
    TranslationBatchEntryParams:
      type: object
      properties:
        resource_type:
          type: string
          description: Translatable resource type token, e.g. `option_type`.
          example: option_type
        resource_id:
          type: string
          example: opt_abc123
        values:
          type: object
          additionalProperties: true
          description: Translated fields keyed by locale code, then by field name.
          example:
            de:
              label: Größe
      required:
      - resource_type
      - resource_id
      - values
    TranslationBatchParams:
      type: object
      properties:
        translations:
          type: array
          items:
            "$ref": "#/components/schemas/TranslationBatchEntryParams"
          description: At least one entry. All entries are saved, or none are.
      required:
      - translations
    VariantCreateParams:
      allOf:
      - "$ref": "#/components/schemas/VariantParams"
      - type: object
        properties:
          options:
            type: array
            items:
              "$ref": "#/components/schemas/VariantOptionParams"
            description: One pair per option type the variant takes part in (size,
              color). Option types and values are created when missing. On update,
              omit to leave the option values untouched.
          external_references:
            type: object
            additionalProperties: true
            description: 'Identities the record has in external systems, keyed by
              system: the same `{ system: external_id }` map the Admin API renders,
              so what you read can be sent straight back. Systems you do not name
              keep the reference they have. A list of `{ system, external_id }` entries
              is accepted too.'
        required:
        - options
    VariantOptionParams:
      type: object
      properties:
        name:
          type: string
          example: size
        value:
          type: string
          example: Small
      required:
      - name
      - value
    VariantParams:
      type: object
      properties:
        sku:
          type: string
        barcode:
          type: string
        cost_price:
          type: string
          format: decimal
          pattern: "^-?\\d+(\\.\\d+)?$"
          nullable: true
        cost_currency:
          "$ref": "#/components/schemas/CurrencyCode"
        weight:
          type: number
          nullable: true
        height:
          type: number
          nullable: true
        width:
          type: number
          nullable: true
        depth:
          type: number
          nullable: true
        weight_unit:
          allOf:
          - "$ref": "#/components/schemas/WeightUnit"
          description: Null falls back to the store's weight unit.
          nullable: true
        dimensions_unit:
          allOf:
          - "$ref": "#/components/schemas/DimensionUnit"
          description: Null falls back to the store's unit system.
          nullable: true
        hs_code:
          type: string
        customs_description:
          type: string
        country_of_origin:
          "$ref": "#/components/schemas/CountryCode"
        minimum_order_quantity:
          type: integer
          nullable: true
        order_multiple:
          type: integer
          nullable: true
        purchase_unit:
          type: string
          enum:
          - unit
          - carton
          nullable: true
        units_per_carton:
          type: integer
          description: How many units fill one carton.
          nullable: true
        carton_package_type_id:
          type: string
          description: 'The carton this variant is packed into: a package type of
            kind `carton`. Its dimensions are shared by every product packed the same
            way, so a corrected carton size fixes all of them at once.'
          nullable: true
        carton_weight:
          type: number
          description: What one packed carton weighs, in the variant's weight unit.
          nullable: true
        cartons_per_pallet:
          type: integer
          description: How many cartons stack on one pallet.
          nullable: true
        track_inventory:
          type: boolean
        preorderable:
          type: boolean
          description: Sell this variant before it's in stock. Adds the pre-order
            label and ships-by promise; the cap comes from `backorder_limit`, an incoming
            stock count, or backorder.
        preorder_ships_at:
          type: string
          format: date-time
          description: The "ships by" date shown to customers while the variant is
            a pre-order. Once it passes, the variant is no longer a pre-order. Null
            clears it.
          nullable: true
        backorder_limit:
          type: integer
          description: Maximum units sellable beyond available stock, capping backorders
            and pre-orders. Null is unlimited.
          nullable: true
        position:
          type: integer
        options:
          type: array
          items:
            "$ref": "#/components/schemas/VariantOptionParams"
          description: One pair per option type the variant takes part in (size, color).
            Option types and values are created when missing.
        seller_id:
          type: string
        delivery_profile_id:
          type: string
          nullable: true
        tax_category_id:
          type: string
        prices:
          type: array
          items:
            "$ref": "#/components/schemas/PriceParams"
          description: Per-currency prices. Upserted by currency.
        stock_levels:
          type: array
          items:
            "$ref": "#/components/schemas/StockLevelParams"
          description: Stock per location. Upserted by location; omitted locations
            are removed.
    VariantSalesContextParams:
      type: object
      properties:
        order_id:
          type: string
          description: 'A draft order to sell to: lists only what its buyer can be
            sold on its channel, priced in its market. Needs `read_orders`, and cannot
            be combined with the fields below.'
        market_id:
          type: string
          description: Prices in this market and lists only variants with a price
            in its currency.
        channel_id:
          type: string
          description: Lists only variants published on this channel. When a market,
            customer, company or currency is given without it, the store default channel
            applies; an order uses its own.
        customer_id:
          type: string
          description: Narrows to the customer's catalogs and prices as they would
            pay. Needs `read_customers`.
        company_id:
          type: string
          description: Narrows to the company's catalogs and prices under its agreement.
            Needs `read_customers`.
        currency:
          allOf:
          - "$ref": "#/components/schemas/CurrencyCode"
          description: Lists only variants with a price in this currency. With `market_id`
            it must be the market's currency.
    VariantUpdateParams:
      allOf:
      - "$ref": "#/components/schemas/VariantParams"
      - type: object
        properties:
          options:
            type: array
            items:
              "$ref": "#/components/schemas/VariantOptionParams"
            description: One pair per option type the variant takes part in (size,
              color). Option types and values are created when missing. On update,
              omit to leave the option values untouched.
          external_references:
            type: object
            additionalProperties: true
            description: 'Identities the record has in external systems, keyed by
              system: the same `{ system: external_id }` map the Admin API renders,
              so what you read can be sent straight back. Systems you do not name
              keep the reference they have. A list of `{ system, external_id }` entries
              is accepted too.'
    WebhookEndpointCreateParams:
      type: object
      properties:
        name:
          type: string
          description: A label shown in the dashboard list.
          example: Order pipeline
          nullable: true
        url:
          type: string
          description: HTTPS destination URL. It cannot resolve to a private IP address
            outside development.
          example: https://example.com/webhooks/orders
        active:
          type: boolean
          description: Defaults to true on create. Prefer the disable and enable endpoints
            to pause one.
        subscriptions:
          type: array
          items:
            type: string
          description: Event names this endpoint receives. An empty list or `["*"]`
            subscribes to every event; otherwise list exact names (`order.completed`)
            or patterns with `*` in place of a segment (`order.*`, `*.created`). At
            most 200 entries of up to 100 characters.
          example:
          - order.placed
          - order.canceled
      required:
      - url
    WebhookEndpointDisableParams:
      type: object
      properties:
        reason:
          type: string
          description: Shown next to the disabled indicator. Defaults to "Manually
            disabled".
          example: Investigating elevated 5xx rate
    WebhookEndpointUpdateParams:
      type: object
      properties:
        name:
          type: string
          description: A label shown in the dashboard list.
          example: Order pipeline
          nullable: true
        url:
          type: string
          description: HTTPS destination URL. It cannot resolve to a private IP address
            outside development.
          example: https://example.com/webhooks/orders
        active:
          type: boolean
          description: Defaults to true on create. Prefer the disable and enable endpoints
            to pause one.
        subscriptions:
          type: array
          items:
            type: string
          description: Event names this endpoint receives. An empty list or `["*"]`
            subscribes to every event; otherwise list exact names (`order.completed`)
            or patterns with `*` in place of a segment (`order.*`, `*.created`). At
            most 200 entries of up to 100 characters.
          example:
          - order.placed
          - order.canceled
  x-spree-filter-tables:
    Address:
      attributes:
        address1: text
        address2: text
        city: text
        company: text
        country_code:
          code: CountryCode
        created_at: datetime
        first_name: text
        id: id
        last_name: text
        phone: text
        postal_code: text
        state_code: text
        updated_at: datetime
      associations: {}
      scopes: {}
    AdminUser:
      attributes:
        created_at: datetime
        email: text
        first_name: text
        id: id
        last_name: text
        updated_at: datetime
      associations:
        spree_roles: Role
      scopes: {}
    AllowedOrigin:
      attributes:
        created_at: datetime
        id: id
        origin: text
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    ApiKey:
      attributes:
        created_at: datetime
        id: id
        name: text
        updated_at: datetime
      associations: {}
      scopes: {}
    Catalog:
      attributes:
        active: boolean
        created_at: datetime
        id: id
        name: text
        position: integer
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    CatalogOrderMinimum:
      attributes:
        created_at: datetime
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    Category:
      attributes:
        automatic: boolean
        children_count: integer
        created_at: datetime
        depth: integer
        id: id
        name: text
        parent_id: id
        permalink: text
        position: integer
        pretty_name: text
        products_count: integer
        updated_at: datetime
      associations:
        parent: Category
      scopes:
        search: text
    Channel:
      attributes:
        active: boolean
        code: text
        created_at: datetime
        default: boolean
        id: id
        name: text
        store_id: id
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    Claim:
      attributes:
        created_at: datetime
        id: id
        number: text
        status:
          enum:
          - open
          - approved
          - resolved
          - denied
          - canceled
        updated_at: datetime
      associations:
        order: Order
        reason: ClaimReason
      scopes:
        search: text
    ClaimReason:
      attributes:
        active: boolean
        created_at: datetime
        id: id
        name: text
        updated_at: datetime
      associations: {}
      scopes: {}
    Collection:
      attributes:
        automatic: boolean
        created_at: datetime
        id: id
        name: text
        permalink: text
        position: integer
        products_count: integer
        sort_order:
          enum:
          - manual
          - best_selling
          - price asc
          - price desc
          - available_on desc
          - available_on asc
          - name asc
          - name desc
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    CommissionLine:
      attributes:
        amount: decimal
        created_at: datetime
        currency:
          code: CurrencyCode
        id: id
        kind:
          enum:
          - percentage
          - fixed
        order_id: id
        rate: decimal
        tax_amount: decimal
        total: decimal
        updated_at: datetime
      associations:
        commission_rate: CommissionRate
        seller: Seller
      scopes: {}
    CommissionRate:
      attributes:
        code: text
        created_at: datetime
        enabled: boolean
        id: id
        include_shipping: boolean
        kind:
          enum:
          - percentage
          - fixed
        name: text
        position: integer
        tax_inclusive: boolean
        updated_at: datetime
        value: decimal
      associations:
        commission_rules: CommissionRule
      scopes:
        search: text
    CommissionRule:
      attributes:
        created_at: datetime
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    Company:
      attributes:
        created_at: datetime
        id: id
        kind:
          enum:
          - company
          - division
        name: text
        parent_id: id
        po_number_required: boolean
        updated_at: datetime
      associations:
        children: Company
        external_references: ExternalReference
        memberships: CompanyMembership
        parent: Company
      scopes:
        search: text
    CompanyInvitation:
      attributes:
        created_at: datetime
        email: text
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    CompanyMembership:
      attributes:
        created_at: datetime
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    ConsentRecord:
      attributes:
        accepted: boolean
        created_at: datetime
        email: text
        id: id
        purpose: text
        recorded_at: datetime
        source:
          enum:
          - checkout
          - registration
          - account
          - admin
          - newsletter
          - anonymization
          - unknown
          - import
          - storefront
        updated_at: datetime
      associations: {}
      scopes: {}
    CouponCode:
      attributes:
        code: text
        created_at: datetime
        id: id
        promotion_id: id
        state:
          enum:
          - unused
          - used
        updated_at: datetime
      associations:
        promotion: Promotion
      scopes: {}
    CreditCard:
      attributes:
        created_at: datetime
        id: id
        name: text
        updated_at: datetime
      associations: {}
      scopes: {}
    CustomField:
      attributes:
        created_at: datetime
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    CustomFieldDefinition:
      attributes:
        created_at: datetime
        field_type: type
        id: id
        key: text
        label: text
        namespace: text
        resource_type: type
        searchable: boolean
        sortable: boolean
        storefront_visible: boolean
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    Customer:
      attributes:
        accepts_email_marketing: boolean
        created_at: datetime
        email: text
        first_name: text
        id: id
        last_name: text
        phone: text
        updated_at: datetime
      associations:
        addresses: Address
        bill_address: Address
        customer_groups: CustomerGroup
        orders: Order
        ship_address: Address
        spree_roles: Role
        tags: Tag
      scopes:
        anonymized: boolean
        search: text
        with_min_total_spent: decimal
        with_standing_for_company:
          list: id
    CustomerGroup:
      attributes:
        created_at: datetime
        id: id
        name: text
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    DataRequest:
      attributes:
        completed_at: datetime
        created_at: datetime
        email: text
        id: id
        kind:
          enum:
          - access
          - erasure
        number: text
        requested_at: datetime
        status:
          enum:
          - awaiting_confirmation
          - pending
          - processing
          - completed
          - failed
          - lapsed
        updated_at: datetime
      associations: {}
      scopes:
        access: boolean
        erasure: boolean
        in_progress: boolean
    Delivery:
      attributes:
        carrier: text
        created_at: datetime
        id: id
        status:
          enum:
          - pending
          - pre_transit
          - in_transit
          - out_for_delivery
          - available_for_pickup
          - delivered
          - return_to_sender
          - failure
          - unknown
        tracking_number: text
        updated_at: datetime
      associations: {}
      scopes: {}
    DeliveryMethod:
      attributes:
        available_to_sellers: boolean
        created_at: datetime
        id: id
        name: text
        seller_id: id
        storefront_visible: boolean
        updated_at: datetime
      associations:
        seller: Seller
      scopes:
        search: text
    DeliveryMethodRule:
      attributes:
        created_at: datetime
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    DeliveryOriginGroup:
      attributes:
        created_at: datetime
        id: id
        name: text
        position: integer
        updated_at: datetime
      associations: {}
      scopes: {}
    DeliveryProfile:
      attributes:
        created_at: datetime
        id: id
        name: text
        position: integer
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    DeliveryZone:
      attributes:
        created_at: datetime
        delivery_profile_id: id
        id: id
        name: text
        updated_at: datetime
      associations: {}
      scopes: {}
    DigitalAsset:
      attributes:
        created_at: datetime
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    DigitalLink:
      attributes:
        created_at: datetime
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    Discount:
      attributes:
        created_at: datetime
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    EmailTemplateRevision:
      attributes:
        created_at: datetime
        id: id
      associations: {}
      scopes: {}
    Exchange:
      attributes:
        created_at: datetime
        id: id
        number: text
        status:
          enum:
          - requested
          - approved
          - received
          - fulfilled
          - canceled
        updated_at: datetime
      associations:
        order: Order
        reason: ReturnReason
      scopes:
        search: text
    Export:
      attributes:
        created_at: datetime
        format:
          enum:
          - csv
        id: id
        number: text
        seller_id: id
        type: type
        updated_at: datetime
      associations:
        seller: Seller
      scopes: {}
    ExternalReference:
      attributes:
        created_at: datetime
        external_id: text
        id: id
        resource_type: type
        system: text
        updated_at: datetime
      associations: {}
      scopes: {}
    Fee:
      attributes:
        created_at: datetime
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    Fulfillment:
      attributes:
        created_at: datetime
        id: id
        number: text
        updated_at: datetime
      associations: {}
      scopes: {}
    GiftCard:
      attributes:
        code: text
        created_at: datetime
        created_by_id: id
        currency:
          code: CurrencyCode
        customer_id: id
        expires_at: date
        gift_card_batch_id: id
        id: id
        state:
          enum:
          - active
          - partially_redeemed
          - redeemed
          - canceled
        status:
          enum:
          - active
          - partially_redeemed
          - redeemed
          - canceled
        updated_at: datetime
      associations:
        batch: GiftCardBatch
        customers: Customer
        orders: Order
        users: Customer
      scopes:
        active: boolean
        expired: boolean
        partially_redeemed: boolean
        redeemed: boolean
        search: text
    GiftCardBatch:
      attributes:
        created_at: datetime
        id: id
        prefix: text
        updated_at: datetime
      associations: {}
      scopes: {}
    Import:
      attributes:
        created_at: datetime
        id: id
        number: text
        seller_id: id
        status:
          enum:
          - pending
          - mapping
          - completed_mapping
          - processing
          - completed
          - failed
        type: type
        updated_at: datetime
      associations:
        seller: Seller
      scopes:
        search: text
    ImportRow:
      attributes:
        created_at: datetime
        id: id
        row_number: integer
        status:
          enum:
          - pending
          - processing
          - completed
          - failed
        updated_at: datetime
      associations: {}
      scopes: {}
    Integration:
      attributes:
        created_at: datetime
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    Invitation:
      attributes:
        created_at: datetime
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    LineItem:
      attributes:
        additional_tax_total: decimal
        adjustment_total: decimal
        cost_price: decimal
        created_at: datetime
        discount_total: decimal
        id: id
        included_tax_total: decimal
        non_taxable_adjustment_total: decimal
        order_id: id
        pre_tax_amount: decimal
        price: decimal
        quantity: integer
        tax_category_id: id
        taxable_adjustment_total: decimal
        updated_at: datetime
        variant_id: id
      associations:
        order: Order
        tax_category: TaxCategory
        variant: Variant
      scopes: {}
    Market:
      attributes:
        created_at: datetime
        currency:
          code: CurrencyCode
        default_locale:
          code: LocaleCode
        id: id
        name: text
        position: integer
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    Media:
      attributes:
        alt: text
        byte_size: integer
        created_at: datetime
        filename: text
        id: id
        media_type:
          enum:
          - image
          - video
          - external_video
        position: integer
        updated_at: datetime
      associations: {}
      scopes:
        attached: boolean
        filename_cont: text
        unattached: boolean
    OptionType:
      attributes:
        created_at: datetime
        id: id
        kind:
          enum:
          - dropdown
          - color_swatch
          - buttons
        label: text
        name: text
        position: integer
        updated_at: datetime
      associations: {}
      scopes:
        search: text
        search_by_name: text
    OptionValue:
      attributes:
        created_at: datetime
        id: id
        label: text
        name: text
        position: integer
        updated_at: datetime
      associations: {}
      scopes: {}
    Order:
      attributes:
        channel_id: id
        completed_at: datetime
        considered_risky: boolean
        coupon_code: text
        created_at: datetime
        currency:
          code: CurrencyCode
        customer_id: id
        delivery_total: decimal
        email: text
        fulfillment_status:
          enum:
          - backorder
          - canceled
          - partial
          - unfulfilled
          - fulfilled
          - delivered
          - pending
          - ready
          - shipped
        id: id
        item_total: decimal
        locale:
          code: LocaleCode
        market_id: id
        number: text
        order_group_id: id
        payment_state:
          enum:
          - none
          - authorized
          - partially_paid
          - paid
          - partially_refunded
          - refunded
          - overcharged
          - voided
          - balance_due
          - credit_owed
          - failed
          - void
        payment_status:
          enum:
          - none
          - authorized
          - partially_paid
          - paid
          - partially_refunded
          - refunded
          - overcharged
          - voided
          - balance_due
          - credit_owed
          - failed
          - void
        po_number: text
        seller_id: id
        shipment_state:
          enum:
          - backorder
          - canceled
          - partial
          - unfulfilled
          - fulfilled
          - delivered
          - pending
          - ready
          - shipped
        status:
          enum:
          - draft
          - placed
          - canceled
        total: decimal
        total_quantity: integer
        updated_at: datetime
      associations:
        bill_address: Address
        channel: Channel
        customer: Customer
        fulfillments: Fulfillment
        line_items: LineItem
        order_group: OrderGroup
        promotions: Promotion
        seller: Seller
        ship_address: Address
        shipments: Fulfillment
        store: Store
        tags: Tag
      scopes:
        complete: boolean
        incomplete: boolean
        partially_refunded: boolean
        refunded: boolean
        search: text
    OrderCancellationReason:
      attributes:
        active: boolean
        created_at: datetime
        id: id
        name: text
        updated_at: datetime
      associations: {}
      scopes: {}
    OrderGroup:
      attributes:
        created_at: datetime
        currency:
          code: CurrencyCode
        email: text
        id: id
        number: text
        updated_at: datetime
      associations:
        customer: Customer
        orders: Order
      scopes: {}
    OrderRoutingRule:
      attributes:
        active: boolean
        channel_id: id
        created_at: datetime
        id: id
        position: integer
        store_id: id
        type: type
        updated_at: datetime
      associations: {}
      scopes: {}
    PackageType:
      attributes:
        created_at: datetime
        default: boolean
        id: id
        kind:
          enum:
          - box
          - envelope
          - carton
          - pallet
          - container
        name: text
        seller_id: id
        updated_at: datetime
      associations:
        seller: Seller
      scopes:
        search: text
    Payment:
      attributes:
        amount: decimal
        avs_response: text
        created_at: datetime
        cvv_response_code: text
        cvv_response_message: text
        id: id
        response_code: text
        state:
          enum:
          - checkout
          - processing
          - pending
          - completed
          - failed
          - void
          - invalid
        status:
          enum:
          - checkout
          - processing
          - pending
          - completed
          - failed
          - void
          - invalid
        updated_at: datetime
      associations:
        order: Order
        payment_method: PaymentMethod
      scopes: {}
    PaymentMethod:
      attributes:
        active: boolean
        created_at: datetime
        id: id
        name: text
        position: integer
        storefront_visible: boolean
        type: type
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    Policy:
      attributes:
        created_at: datetime
        id: id
        name: text
        owner_id: id
        owner_type: type
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    Price:
      attributes:
        amount: decimal
        compare_at_amount: decimal
        created_at: datetime
        currency:
          code: CurrencyCode
        id: id
        min_quantity: integer
        price_list_id: id
        updated_at: datetime
        variant_id: id
      associations:
        price_list: PriceList
        variant: Variant
      scopes:
        search: text
    PriceList:
      attributes:
        catalog_id: id
        created_at: datetime
        ends_at: datetime
        id: id
        match_policy:
          enum:
          - all
          - any
        name: text
        position: integer
        starts_at: datetime
        status:
          enum:
          - draft
          - active
          - inactive
          - scheduled
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    Product:
      attributes:
        available_on: datetime
        created_at: datetime
        description: text
        discontinue_on: datetime
        id: id
        name: text
        price: decimal
        seller_id: id
        slug: text
        status:
          enum:
          - draft
          - active
          - archived
          - proposed
          - rejected
        updated_at: datetime
      associations:
        categories: Category
        channels: Channel
        collections: Collection
        default_variant: Variant
        labels: Tag
        option_types: OptionType
        product_categories: ProductCategory
        product_type: ProductType
        seller: Seller
        store: Store
        tags: Tag
        variants: Variant
      scopes:
        ascend_by_price: boolean
        descend_by_price: boolean
        in_categories:
          list: id
        in_category: id
        in_collection: id
        in_stock: boolean
        in_taxon: id
        not_discontinued: boolean
        out_of_stock: boolean
        price_between:
        - decimal
        - decimal
        price_gte: decimal
        price_lte: decimal
        search: text
        search_by_name: text
        with_option_value_ids:
          list: id
    ProductCategory:
      attributes:
        category_id: id
        created_at: datetime
        id: id
        position: integer
        product_id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    ProductType:
      attributes:
        created_at: datetime
        id: id
        name: text
        updated_at: datetime
      associations:
        option_types: OptionType
      scopes:
        search: text
    Promotion:
      attributes:
        code: text
        created_at: datetime
        expires_at: datetime
        id: id
        kind:
          enum:
          - coupon_code
          - automatic
        name: text
        path: text
        promotion_category_id: id
        starts_at: datetime
        updated_at: datetime
      associations:
        coupon_codes: CouponCode
      scopes:
        search: text
    PromotionAction:
      attributes:
        created_at: datetime
        id: id
        position: integer
        updated_at: datetime
      associations: {}
      scopes: {}
    PromotionRule:
      attributes:
        created_at: datetime
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    PurchaseOrder:
      attributes:
        cancel_by: date
        closed_short_at: datetime
        created_at: datetime
        currency:
          code: CurrencyCode
        destination_location_id: id
        expected_at: date
        id: id
        number: text
        ordered_at: datetime
        received_at: datetime
        reference: text
        status:
          enum:
          - draft
          - ordered
          - partially_received
          - received
          - over_received
          - canceled
        supplier_id: id
        updated_at: datetime
      associations:
        destination_location: StockLocation
        items: PurchaseOrderItem
        supplier: Supplier
      scopes:
        closed: boolean
        open: boolean
        overdue: boolean
        past_cancel_by: boolean
        search: text
    PurchaseOrderItem:
      attributes:
        created_at: datetime
        id: id
        quantity_ordered: integer
        quantity_received: integer
        quantity_rejected: integer
        unit_cost: decimal
        updated_at: datetime
        variant_id: id
      associations:
        variant: Variant
      scopes: {}
    Refund:
      attributes:
        created_at: datetime
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    RefundReason:
      attributes:
        active: boolean
        created_at: datetime
        id: id
        name: text
        updated_at: datetime
      associations: {}
      scopes: {}
    Return:
      attributes:
        created_at: datetime
        id: id
        number: text
        status:
          enum:
          - requested
          - approved
          - received
          - refunded
          - canceled
        updated_at: datetime
      associations:
        order: Order
        reason: ReturnReason
      scopes:
        search: text
    ReturnReason:
      attributes:
        active: boolean
        created_at: datetime
        id: id
        name: text
        updated_at: datetime
      associations: {}
      scopes: {}
    Role:
      attributes:
        created_at: datetime
        id: id
        name: text
        updated_at: datetime
      associations: {}
      scopes: {}
    SavedReport:
      attributes:
        created_at: datetime
        id: id
        name: text
        seeded: boolean
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    Seller:
      attributes:
        contact_email: text
        created_at: datetime
        id: id
        name: text
        status:
          enum:
          - pending
          - invited
          - canceled
          - onboarding
          - ready_for_review
          - approved
          - rejected
          - suspended
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    SellerPayout:
      attributes:
        amount: decimal
        created_at: datetime
        currency:
          code: CurrencyCode
        id: id
        period_end: datetime
        period_start: datetime
        provider: text
        reference: text
        seller_id: id
        status:
          enum:
          - pending
          - processing
          - completed
          - failed
          - unresolved
        updated_at: datetime
      associations:
        seller: Seller
      scopes:
        search: text
    SellerRequirement:
      attributes:
        created_at: datetime
        id: id
        name: text
        position: integer
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    SellerRequirementSubmission:
      attributes:
        created_at: datetime
        id: id
        reviewed_at: datetime
        status:
          enum:
          - pending
          - accepted
          - rejected
          - waived
        updated_at: datetime
      associations:
        requirement: SellerRequirement
        seller: Seller
      scopes: {}
    SellerTransfer:
      attributes:
        amount: decimal
        created_at: datetime
        currency:
          code: CurrencyCode
        id: id
        kind:
          enum:
          - earning
          - refund_reversal
        order_id: id
        payout_id: id
        provider: text
        reference: text
        seller_id: id
        status:
          enum:
          - pending
          - processing
          - completed
          - failed
          - unresolved
        updated_at: datetime
      associations:
        payout: SellerPayout
        refund: Refund
        seller: Seller
      scopes:
        search: text
    ShippingLabel:
      attributes:
        carrier: text
        created_at: datetime
        id: id
        source:
          enum:
          - purchased
          - uploaded
        status:
          enum:
          - purchased
          - refund_requested
          - refunded
        tracking_number: text
        updated_at: datetime
      associations: {}
      scopes: {}
    StockLevel:
      attributes:
        allocated_count: integer
        count_on_hand: integer
        created_at: datetime
        id: id
        incoming_count: integer
        reserved_count: integer
        stock_location_id: id
        updated_at: datetime
        variant_id: id
      associations:
        stock_location: StockLocation
        variant: Variant
      scopes:
        search: text
        with_stock_status:
          list: text
    StockLocation:
      attributes:
        active: boolean
        country_code:
          code: CountryCode
        created_at: datetime
        default: boolean
        id: id
        kind: text
        name: text
        pickup_enabled: boolean
        returns_enabled: boolean
        seller_id: id
        state_code: text
        updated_at: datetime
      associations:
        seller: Seller
      scopes:
        search: text
    StockMovement:
      attributes:
        created_at: datetime
        exchange_id: id
        fulfillment_id: id
        id: id
        kind:
          enum:
          - received
          - allocated
          - shipped
          - released
          - adjusted
        order_id: id
        purchase_order_id: id
        quantity: integer
        reason: text
        return_id: id
        stock_item_id: id
        stock_level_id: id
        stock_receipt_id: id
        stock_transfer_id: id
        unit_cost: decimal
        updated_at: datetime
      associations:
        stock_level: StockLevel
      scopes: {}
    StockReceipt:
      attributes:
        created_at: datetime
        id: id
        number: text
        receivable_id: id
        receivable_type: type
        received_at: datetime
        received_by_id: id
        received_by_type: type
        reference: text
        updated_at: datetime
      associations: {}
      scopes: {}
    StockReservation:
      attributes:
        created_at: datetime
        expires_at: datetime
        id: id
        line_item_id: id
        order_id: id
        quantity: integer
        stock_item_id: id
        stock_level_id: id
        updated_at: datetime
      associations:
        line_item: LineItem
        order: Order
        stock_level: StockLevel
      scopes: {}
    StockTransfer:
      attributes:
        closed_short_at: datetime
        created_at: datetime
        destination_location_id: id
        id: id
        number: text
        received_at: datetime
        reference: text
        shipped_at: datetime
        source_location_id: id
        status:
          enum:
          - draft
          - ready_to_ship
          - in_transit
          - partially_received
          - received
          - over_received
          - canceled
        updated_at: datetime
      associations:
        destination_location: StockLocation
        items: StockTransferItem
        source_location: StockLocation
      scopes:
        closed: boolean
        open: boolean
        search: text
    StockTransferItem:
      attributes:
        created_at: datetime
        id: id
        quantity_received: integer
        quantity_rejected: integer
        quantity_shipped: integer
        updated_at: datetime
        variant_id: id
      associations:
        variant: Variant
      scopes: {}
    Store:
      attributes:
        created_at: datetime
        id: id
        name: text
        updated_at: datetime
      associations: {}
      scopes: {}
    StoreCredit:
      attributes:
        amount: decimal
        created_at: datetime
        created_by_id: id
        currency:
          code: CurrencyCode
        customer_id: id
        id: id
        memo: text
        updated_at: datetime
      associations:
        customer: Customer
      scopes:
        from_gift_card: boolean
        outstanding: boolean
        search: text
    StoreCreditEvent:
      attributes:
        created_at: datetime
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    Supplier:
      attributes:
        city: text
        contact_name: text
        country_code:
          code: CountryCode
        created_at: datetime
        email: text
        id: id
        name: text
        phone: text
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    Tag:
      attributes:
        created_at: datetime
        id: id
        name: text
        updated_at: datetime
      associations: {}
      scopes: {}
    TaxCategory:
      attributes:
        created_at: datetime
        id: id
        is_default: boolean
        name: text
        tax_code: text
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    TaxExemptionCertificate:
      attributes:
        certificate_number: text
        created_at: datetime
        expires_at: datetime
        id: id
        status:
          enum:
          - pending
          - verified
          - expired
          - revoked
        tax_exemption_reason_id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    TaxExemptionReason:
      attributes:
        active: boolean
        code: text
        created_at: datetime
        id: id
        name: text
        updated_at: datetime
      associations: {}
      scopes: {}
    TaxIdentifier:
      attributes:
        created_at: datetime
        id: id
        updated_at: datetime
      associations: {}
      scopes: {}
    TaxLine:
      attributes:
        country_code:
          code: CountryCode
        created_at: datetime
        id: id
        included: boolean
        provider_id: text
        state_code: text
        taxability_reason: text
        updated_at: datetime
      associations: {}
      scopes: {}
    TaxRate:
      attributes:
        amount: decimal
        country_code:
          code: CountryCode
        created_at: datetime
        id: id
        name: text
        rate: decimal
        state_code: text
        tax_category_id: id
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    Variant:
      attributes:
        carton_package_type_id: id
        carton_weight: decimal
        cartons_per_pallet: integer
        cost_currency:
          code: CurrencyCode
        cost_price: decimal
        country_of_origin:
          code: CountryCode
        created_at: datetime
        deleted_at: datetime
        depth: decimal
        discontinue_on: datetime
        height: decimal
        hs_code: text
        id: id
        minimum_order_quantity: integer
        order_multiple: integer
        position: integer
        product_id: id
        purchase_unit:
          enum:
          - unit
          - carton
        sku: text
        track_inventory: boolean
        units_per_carton: integer
        updated_at: datetime
        weight: decimal
        width: decimal
      associations:
        option_values: OptionValue
        prices: Price
        product: Product
        seller: Seller
        tax_category: TaxCategory
      scopes:
        available_at_stock_location: id
        product_name_or_sku_cont: text
        search: text
        search_by_product_name_or_sku: text
    WebhookDelivery:
      attributes:
        created_at: datetime
        delivered_at: datetime
        event_name: text
        execution_time: integer
        id: id
        response_code: integer
        success: boolean
        updated_at: datetime
      associations: {}
      scopes:
        search: text
    WebhookEndpoint:
      attributes:
        active: boolean
        created_at: datetime
        id: id
        name: text
        updated_at: datetime
        url: text
      associations: {}
      scopes:
        search: text
  x-spree-filter-predicates:
    text:
    - eq
    - not_eq
    - in
    - not_in
    - cont
    - i_cont
    - not_cont
    - start
    - end
    - 'null'
    - not_null
    - present
    - blank
    decimal:
    - eq
    - not_eq
    - in
    - not_in
    - lt
    - lteq
    - gt
    - gteq
    - 'null'
    - not_null
    integer:
    - eq
    - not_eq
    - in
    - not_in
    - lt
    - lteq
    - gt
    - gteq
    - 'null'
    - not_null
    date:
    - eq
    - not_eq
    - in
    - not_in
    - lt
    - lteq
    - gt
    - gteq
    - 'null'
    - not_null
    datetime:
    - eq
    - not_eq
    - in
    - not_in
    - lt
    - lteq
    - gt
    - gteq
    - 'null'
    - not_null
    enum:
    - eq
    - not_eq
    - in
    - not_in
    - 'null'
    - not_null
    id:
    - eq
    - not_eq
    - in
    - not_in
    - 'null'
    - not_null
    type:
    - eq
    - not_eq
    - in
    - not_in
    - 'null'
    - not_null
    boolean:
    - eq
    - not_eq
    - in
    - not_in
    - 'true'
    - 'false'
    - 'null'
