Skip to main content

python3 base API client for shopware6

Project description

lib_shopware6_api_base

CI CodeQL License: MIT Open in Codespaces PyPI PyPI - Downloads Code Style: Ruff codecov Maintainability security: bandit

A Python base API client for Shopware 6, supporting Windows, Linux, and macOS. Supports all OAuth2 authentication methods for both Admin API and Storefront API. Paginated requests are fully supported.

This is the base abstraction layer. For higher-level functions, see lib_shopware6_api.

Python 3.10+ required.


v3.0.0 (2026-02-03) - complete overhaul

Breaking Changes:

  • Migrated from attrs to Pydantic for all data models (Criteria, Filters, Aggregations, Sorting)
  • Migrated HTTP client from requests/requests-oauthlib to httpx/authlib
  • Migrated OAuth2 from oauthlib to authlib (OAuth 2.1 compliant)
  • Minimum Python version raised to 3.10+
  • Filter/Criteria classes now require keyword arguments: EqualsFilter(field="x", value=1) instead of EqualsFilter("x", 1)
  • Environment variables use SHOPWARE_ prefix to avoid collision with system variables (e.g., Windows USERNAME).

New Features:

  • load_config_from_env() and require_config_from_env() for .env file loading
  • ConfigurationError exception for configuration issues
  • ExitCode enum for CLI exit codes
  • HTTP/2 support via httpx
  • ~20-30% performance improvement from httpx

Table of Contents


Configuration

Configuration is managed via the ConfShopware6ApiBase class (Pydantic) and loaded through lib_layered_config, which merges, in increasing precedence:

bundled defaults  ->  app  ->  host  ->  user  ->  .env  ->  environment variables

You can also instantiate ConfShopware6ApiBase(...) directly with keyword arguments.

⚠️ Breaking change in 4.0.0 — env vars renamed. Configuration moved to lib_layered_config, so the old single-underscore SHOPWARE_* variables are no longer read. Rename them to the [shopware] section form:

Old (≤ 3.x) New — .env file New — environment variable
SHOPWARE_ADMIN_API_URL SHOPWARE__ADMIN_API_URL LIB_SHOPWARE6_API_BASE___SHOPWARE__ADMIN_API_URL
SHOPWARE_STOREFRONT_API_URL SHOPWARE__STOREFRONT_API_URL LIB_SHOPWARE6_API_BASE___SHOPWARE__STOREFRONT_API_URL
SHOPWARE_<NAME> SHOPWARE__<NAME> LIB_SHOPWARE6_API_BASE___SHOPWARE__<NAME>

i.e. in a .env file replace the single _ after SHOPWARE with __; as a real environment variable also add the LIB_SHOPWARE6_API_BASE___ slug prefix.

Environment File (.env)

Copy example.env to .env and adjust values for your shop:

# API Endpoints
SHOPWARE__ADMIN_API_URL="https://shop.example.com/api"
SHOPWARE__STOREFRONT_API_URL="https://shop.example.com/store-api"

# Transport (set to "1" only for local HTTP development)
SHOPWARE__INSECURE_TRANSPORT="0"

# User-Credentials grant (interactive apps with refresh tokens)
SHOPWARE__USERNAME="admin@example.com"
SHOPWARE__PASSWORD="your-password"

# Resource-Owner grant (automation/CLI - no refresh tokens)
SHOPWARE__CLIENT_ID="SWIAXXXXXXXXXXXXXXXXXXXX"
SHOPWARE__CLIENT_SECRET="your-integration-secret"

# Grant type: USER_CREDENTIALS or RESOURCE_OWNER
SHOPWARE__GRANT_TYPE="RESOURCE_OWNER"

# Storefront API access key (from Sales Channel settings)
SHOPWARE__STORE_API_SW_ACCESS_KEY="SWSCXXXXXXXXXXXXXXXXXX"

[shopware] Settings Reference

In a .env file use the SHOPWARE__<KEY> form; as a real environment variable prefix with LIB_SHOPWARE6_API_BASE___. The same keys can be set in a TOML config file under [shopware] (dropping the SHOPWARE__ prefix).

.env key Description Example
SHOPWARE__ADMIN_API_URL Admin API endpoint https://shop.example.com/api
SHOPWARE__STOREFRONT_API_URL Storefront API endpoint https://shop.example.com/store-api
SHOPWARE__INSECURE_TRANSPORT Allow HTTP (dev only) 0 (production) or 1 (dev)
SHOPWARE__USERNAME Admin user email admin@example.com
SHOPWARE__PASSWORD Admin user password secret
SHOPWARE__CLIENT_ID Integration Access ID SWIA...
SHOPWARE__CLIENT_SECRET Integration Secret ...
SHOPWARE__GRANT_TYPE Auth method USER_CREDENTIALS or RESOURCE_OWNER
SHOPWARE__STORE_API_SW_ACCESS_KEY Storefront access key SWSC...

Loading Configuration

from lib_shopware6_api_base import (
    ConfShopware6ApiBase,
    load_config_from_env,
    require_config_from_env,
    Shopware6AdminAPIClientBase,
)

# Option 1: Auto-find .env in current or parent directories
config = load_config_from_env()

# Option 2: Require .env file (raises ConfigurationError if not found)
config = require_config_from_env()

# Option 3: Load from specific file
config = load_config_from_env("/path/to/my.env")

# Option 4: Direct instantiation
config = ConfShopware6ApiBase(
    shopware_admin_api_url="https://shop.example.com/api",
    username="admin",
    password="secret",
)

# Use the config
client = Shopware6AdminAPIClientBase(config=config)

API Clients

Admin API

from lib_shopware6_api_base import Shopware6AdminAPIClientBase, Criteria

client = Shopware6AdminAPIClientBase(config=config)

# GET request
response = client.request_get("currency")

# GET with pagination (fetches all records in chunks)
response = client.request_get_paginated("product", junk_size=100)

# POST request (search)
criteria = Criteria(limit=10)
response = client.request_post("search/product", payload=criteria)

# POST with pagination
response = client.request_post_paginated("search/order", payload=criteria, junk_size=50)

# PATCH request (update)
client.request_patch("product/abc123", payload={"name": "New Name"})

# PUT request (upsert)
client.request_put("tag/xyz789", payload={"id": "xyz789", "name": "My Tag"})

# DELETE request
client.request_delete("tag/xyz789")

Storefront API

from lib_shopware6_api_base import Shopware6StoreFrontClientBase, Criteria

client = Shopware6StoreFrontClientBase(config=config)

# GET request (returns dict)
response = client.request_get("context")

# GET request (returns list)
currencies = client.request_get_list("currency")

# POST request with criteria
criteria = Criteria(limit=5)
products = client.request_post("product", payload=criteria)

Request Methods

All request methods accept these parameters:

Parameter Type Description
request_url str API endpoint (without base URL)
payload dict | Criteria | None Request body
update_header_fields dict[str, str] | None Custom headers

Admin API methods also support:

Parameter Type Description
content_type str Content type (json, octet-stream)
additional_query_params dict URL query parameters

Custom Headers

For bulk operations, use predefined header constants:

from lib_shopware6_api_base import (
    HEADER_write_in_single_transactions,  # {"single-operation": "true"}
    HEADER_write_in_separate_transactions,  # {"single-operation": "false"}
    HEADER_index_synchronously,  # {"indexing-behavior": "null"}
    HEADER_index_asynchronously,  # {"indexing-behavior": "use-queue-indexing"}
    HEADER_index_disabled,  # {"indexing-behavior": "disable-indexing"}
    HEADER_fail_on_error,  # {"fail-on-error": "true"}
    HEADER_do_not_fail_on_error,  # {"fail-on-error": "false"}
)

# Combine headers
headers = HEADER_write_in_single_transactions | HEADER_index_asynchronously
client.request_post("_action/sync", payload=data, update_header_fields=headers)

Query Syntax (Criteria)

The Criteria class (Pydantic model) mirrors Shopware's DAL query syntax:

from lib_shopware6_api_base import Criteria, EqualsFilter, AscFieldSorting

criteria = Criteria(
    limit=10,
    page=1,
    filter=[EqualsFilter(field="active", value=True)],
    sort=[AscFieldSorting(field="name")],
)

Filters

from lib_shopware6_api_base import (
    EqualsFilter,
    EqualsAnyFilter,
    ContainsFilter,
    RangeFilter,
    PrefixFilter,
    SuffixFilter,
    NotFilter,
    MultiFilter,
    FilterOperator,
    RangeParam,
)

# Exact match
EqualsFilter(field="stock", value=10)

# Match any of values
EqualsAnyFilter(field="id", value=["abc", "def"])

# LIKE '%value%'
ContainsFilter(field="name", value="Bronze")

# LIKE 'value%'
PrefixFilter(field="name", value="Pro")

# LIKE '%value'
SuffixFilter(field="sku", value="-XL")

# Range filter
RangeFilter(field="price", parameters={RangeParam.GTE: 10, RangeParam.LTE: 100})
# Or with strings: parameters={"gte": 10, "lte": 100}

# NOT filter
NotFilter(operator="or", queries=[
    EqualsFilter(field="stock", value=0),
    EqualsFilter(field="active", value=False),
])

# Multi filter (combine with AND/OR)
MultiFilter(operator="and", queries=[
    EqualsFilter(field="active", value=True),
    ContainsFilter(field="name", value="Premium"),
])

Sorting

from lib_shopware6_api_base import FieldSorting, AscFieldSorting, DescFieldSorting

# Generic sorting
FieldSorting(field="name", order="ASC", naturalSorting=True)

# Shorthand ascending
AscFieldSorting(field="name", naturalSorting=True)

# Shorthand descending
DescFieldSorting(field="price")

Aggregations

from lib_shopware6_api_base import (
    AvgAggregation,
    CountAggregation,
    MaxAggregation,
    MinAggregation,
    SumAggregation,
    StatsAggregation,
    TermsAggregation,
    FilterAggregation,
    EntityAggregation,
    DateHistogramAggregation,
)

criteria = Criteria(
    aggregations=[
        AvgAggregation(name="avg-price", field="price"),
        TermsAggregation(name="manufacturers", field="manufacturerId", limit=10),
        FilterAggregation(
            name="active-avg",
            filter=[EqualsFilter(field="active", value=True)],
            aggregation=AvgAggregation(name="price", field="price"),
        ),
    ]
)

Associations

Load related entities:

criteria = Criteria()
criteria.associations["manufacturer"] = Criteria()
criteria.associations["categories"] = Criteria(limit=5)

Error Handling

The library provides specific exception classes for different error scenarios:

from lib_shopware6_api_base import (
    ShopwareAPIError,
    ConfigurationError,
    Shopware6AdminAPIClientBase,
    load_config_from_env,
)

# Handle configuration errors
try:
    config = load_config_from_env("/path/to/missing.env")
except ConfigurationError as e:
    print(f"Configuration error: {e}")
    # Handle missing or invalid configuration

# Handle API errors
try:
    client = Shopware6AdminAPIClientBase(config=config)
    response = client.request_get("product/invalid-id")
except ShopwareAPIError as e:
    print(f"API error: {e}")
    # Handle API errors (404, 401, 500, etc.)

Exception Types

Exception When Raised
ConfigurationError Missing .env file, invalid configuration values
ShopwareAPIError HTTP errors from the API (4xx, 5xx responses)

CLI Usage

Usage: lib_shopware6_api_base [OPTIONS] COMMAND [ARGS]...

  Python base API client for Shopware 6

Options:
  --version                     Show version and exit
  --traceback / --no-traceback  Show traceback on errors
  -h, --help                    Show this message and exit

Commands:
  info  Show program information

Installation

Via uv (recommended)

# One-shot run
uvx lib_shopware6_api_base --help

# Install as CLI tool
uv tool install lib_shopware6_api_base

# Install as dependency
uv pip install lib_shopware6_api_base

Via pip

pip install lib_shopware6_api_base

Development

Project automation runs through a Makefile that delegates to bmk (installed automatically as a persistent uv tool on first use). Run make help to list all targets.

Running tests

make test               # lint (ruff), type-check (pyright), import-linter,
                        # bandit, pip-audit, and the unit test suite with coverage
make testintegration    # integration tests only (see prerequisites below)

make test runs the full quality gate but excludes the integration tests (pytest -m "not integration"). make testintegration runs only the integration suite (pytest -m integration).

Integration tests

The integration tests exercise the Admin and Storefront clients against a real Shopware instance using the dockware container. The test harness starts and stops the container automatically — no manual setup or credentials are required (tests/docker.env ships the dockware defaults).

Prerequisites:

  • Docker installed and running, with a Linux container engine (docker info --format '{{.OSType}}'linux). If Docker is unavailable or not Linux, the integration tests are skipped (not failed).
  • Port 80 free — the container is published on -p 80:80.
  • First run pulls dockware/dev:latest (a few GB), so it takes a while.

Tip: for fast repeated runs, start the container once and leave it up — the harness reuses a running container (and only tears down one it started itself):

docker run -d --rm -p 80:80 --name dockware dockware/dev:latest
make testintegration    # reuses the running container, finishes in seconds

CI runs the unit and integration suites as separate jobs across Linux, macOS, and Windows for Python 3.10–3.14.


Requirements

Automatically installed dependencies:

  • pydantic>=2.0.0 - Data validation
  • pydantic-settings>=2.0.0 - Settings management
  • httpx2>=2.2.0 - HTTP client
  • rich-click - CLI formatting
  • orjson - Fast JSON serialization
  • lib_cli_exit_tools>=2.2.4 - CLI utilities

License

MIT License

Contributing

See CONTRIBUTING.md for guidelines.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

lib_shopware6_api_base-5.0.0.tar.gz (79.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

lib_shopware6_api_base-5.0.0-py3-none-any.whl (45.3 kB view details)

Uploaded Python 3

File details

Details for the file lib_shopware6_api_base-5.0.0.tar.gz.

File metadata

  • Download URL: lib_shopware6_api_base-5.0.0.tar.gz
  • Upload date:
  • Size: 79.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for lib_shopware6_api_base-5.0.0.tar.gz
Algorithm Hash digest
SHA256 8742de669d91a14ea4830931664f87b29b10d7bf528da481435d34cba5424252
MD5 392cad4259b3bb435acfc8b27a138914
BLAKE2b-256 ed8c8e44738b5c57001718f732e243797444eb443eec3de5337bd1c8a4a4a356

See more details on using hashes here.

File details

Details for the file lib_shopware6_api_base-5.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for lib_shopware6_api_base-5.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9b24433e2421919e38f6039fd3b5a80a19effefdccb842f2f1733c93980c69af
MD5 caeb6d93817d73a6c9cc6d0d6ffeab68
BLAKE2b-256 7afa7c392808d30edbcc7fa13223014bd97afbb937eca55399b4cae681b2cebd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page