Skip to main content

using-b2c-tooling-sdk

Consuming the salesforce-b2c-tooling-sdk Python SDK from scripts or Jupyter notebooks — installation, choosing an authentication mechanism, and the available OCAPI/SCAPI/WebDAV clients and operations. Use when writing Python (or notebook) code that authenticates to a B2C Commerce instance, resolves config from dw.json, deploys code, runs jobs, reads sites/catalogs/logs/metrics, provisions sandboxes, or mints SLAS shopper tokens.

ソース情報

リポジトリ
SalesforceCommerceCloud/b2c-developer-tooling
ソースの最終更新活動
2026年9月21日 14:59
検出された SKILL.md の言語
英語
スター
54
フォーク
21

インストール方法

デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。

ソースファイルを確認

インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。

ファイルエクスプローラー
2 ファイル

SKILL.md を表示中

SKILL.md
ソースの指示 · 読み取り専用プレビュー
name
using-b2c-tooling-sdk
description
Consuming the salesforce-b2c-tooling-sdk Python SDK from scripts or Jupyter notebooks — installation, choosing an authentication mechanism, and the available OCAPI/SCAPI/WebDAV clients and operations. Use when writing Python (or notebook) code that authenticates to a B2C Commerce instance, resolves config from dw.json, deploys code, runs jobs, reads sites/catalogs/logs/metrics, provisions sandboxes, or mints SLAS shopper tokens.
# Using the B2C Tooling SDK (Python) `salesforce-b2c-tooling-sdk` is the Python SDK for Salesforce B2C Commerce tooling. **Import name is `b2c_tooling_sdk`; distribution name is `salesforce-b2c-tooling-sdk`.** It is async-first with a complete synchronous facade. Python 3.10+. This skill covers **consuming** the SDK. For developing the SDK itself, see `python/b2c-tooling-sdk/CLAUDE.md`. For the full symbol catalog, read [references/api-catalog.md](references/api-catalog.md). ## 1. Install Not on PyPI yet — install from git during development: ```bash pip install "git+https://github.com/SalesforceCommerceCloud/b2c-developer-tooling.git@main#subdirectory=python/b2c-tooling-sdk" # or pin a release tag: ...@<tag>#subdirectory=python/b2c-tooling-sdk ``` For notebooks also install a kernel: `pip install ipykernel`. Once published this becomes `pip install salesforce-b2c-tooling-sdk`. ## 2. Async vs. sync — pick the import root The two surfaces are identical **except one word**: sync drops `await`. | Context | Import from | Style | | --- | --- | --- | | Scripts / notebooks / REPL | `b2c_tooling_sdk.sync` | blocking, no `await` | | Inside an existing event loop (web server, async app) | `b2c_tooling_sdk` | `await` | **Notebooks: use the sync facade** — it is the frictionless path (no `asyncio.run`, no `await`). All sync calls run on one shared background loop, so token caching still works. ```python # Notebook / script (sync) from b2c_tooling_sdk.sync import resolve_config from b2c_tooling_sdk.sync import list_code_versions config = resolve_config() # blocks instance = config.create_b2c_instance() for v in list_code_versions(instance): print(v.id, "active" if v.active else "") ``` ```python # Async import asyncio from b2c_tooling_sdk import resolve_config from b2c_tooling_sdk.operations.code import list_code_versions async def main() -> None: config = await resolve_config() instance = config.create_b2c_instance() for v in await list_code_versions(instance): print(v.id) asyncio.run(main()) ``` > **Never call the sync facade from inside a running event loop** (including > async notebook cells / `await`-ing cells) — it waits on a background loop and > can deadlock. In async code, import from `b2c_tooling_sdk` and `await`. > > **Streaming APIs (`tail_logs`, cartridge watching) are async-only** — not in > the sync facade. Use the async API for those. The examples below use the **async** form. For sync, import the same names from `b2c_tooling_sdk.sync` and drop `await`. ## 3. Authenticate — choose by use case Credentials usually come from a `dw.json` via `resolve_config()` (see §4). If you already have a `dw.json`, **prefer `resolve_config` + `create_b2c_instance()`** — it selects the auth mechanism for you. Reach for an explicit strategy only when you have no config file or need a specific flow. | Use case | Mechanism | How | | --- | --- | --- | | Server-to-server automation (CI, scripts) | OAuth **client-credentials** | `OAuthStrategy(OAuthConfig(client_id, client_secret, scopes))` | | Server-to-server with a cert instead of a secret | **JWT Bearer** | `JwtOAuthStrategy(JwtOAuthConfig(client_id, cert_path, key_path, ...))` | | Interactive user login (opens a browser) | **PKCE** (+ implicit fallback) | `create_user_auth_strategy(PkceOAuthConfig(client_id=..., account_manager_host=...))` | | Reuse a session created by `b2c auth login` | shared session store | `resolve_config()` picks it up automatically; or `find_auth_session(client_id)` | | WebDAV / OCAPI Basic auth | **Basic** | `BasicAuthStrategy(username, password)` | | Static API key header | **API key** | `ApiKeyStrategy("my-key")` | | Storefront **shopper** tokens (guest/registered) | **SLAS** | `b2c_tooling_sdk.slas.get_guest_token(...)` — see §6 | ```python from b2c_tooling_sdk.auth import OAuthStrategy, OAuthConfig auth = OAuthStrategy(OAuthConfig( client_id="...", client_secret="...", scopes=["sfcc.products"], )) ``` **CLI interoperability:** the SDK shares the *same* on-disk `auth-sessions.json` and config files as the `@salesforce/b2c-cli`. Recommended interactive workflow: run `b2c auth login <clientId>` once, then run non-interactive Python — it reuses the session with no browser prompt. `find_auth_session`, `is_auth_session_token_valid`, and `list_auth_sessions` inspect the store. Don't know which methods a credential bundle supports? Use `resolve_auth_strategy(AuthCredentials(...), allowed_methods=[...])` to pick the best available, or `check_available_auth_methods(...)` to probe without side effects. ## 4. Resolve config from `dw.json` `resolve_config()` merges the same sources the CLI reads (`dw.json` walking up from cwd, `~/.mobify`, `package.json`, `settings.json`) into a resolved config whose `.create_b2c_instance()` builds an authenticated `B2CInstance`. ```python from b2c_tooling_sdk import resolve_config, NormalizedConfig config = await resolve_config() # from dw.json etc. instance = config.create_b2c_instance() # ...or pass explicit overrides instead of a file: config = await resolve_config(NormalizedConfig( hostname="example.demandware.net", client_id="...", client_secret="...", scopes=["sfcc.products"], )) ``` Multi-environment `dw.json` (a `configs` array of named envs): select one with `resolve_config(options=ResolveConfigOptions(instance="staging"))` (priority: requested name → `active: true` → root). Manage entries with `add_instance` / `remove_instance` / `set_active_instance` from `b2c_tooling_sdk.config`. ## 5. Call the APIs — two layers **Choose the layer by how you want errors handled:** - **Operations** (`b2c_tooling_sdk.operations.*`, common ones re-exported at top level) — task-oriented, **success-or-raise**. Straight-line code; failures raise typed exceptions (`JobExecutionError`, sandbox polling errors, ...). **Prefer this for most work.** - **Clients** (`instance.ocapi`, `instance.webdav`, SCAPI `create_*_client`) — low-level. Every call returns a `ClientResult(data, error, response)` and **never raises on 4xx/5xx** (only a genuine network failure raises `NetworkError`). Use when you want to inspect status codes yourself. ```python # Operation (raises on failure) from b2c_tooling_sdk.operations.jobs import execute_job, wait_for_job execution = await execute_job(instance, "MyJob") finished = await wait_for_job(instance, "MyJob", execution.id) # raises JobExecutionError on failure # Client (never raises on HTTP status) result = await instance.ocapi.get("/sites") if result.error is not None: print("failed:", result.response.status_code, result.error) else: for site in result.data.get("data", []): print(site["id"]) ``` **What's available** (full lists in [references/api-catalog.md](references/api-catalog.md)): - **Code** — `find_and_deploy_cartridges`, `list_code_versions`, `create_code_version`, `activate_code_version`. Deploy needs `instance.config.code_version` set. - **Jobs** — `execute_job`, `wait_for_job`, `site_archive_import`, `site_archive_export_to_path` (+ `scapi_*` native variants). - **Sites** — `get_cartridge_path`, `add_cartridge`. - **Catalogs / BM users / BM roles** — dual-backend (SCAPI→OCAPI) façades: `create_catalogs_backend`, `create_users_backend`, `create_roles_backend`. - **ODS (sandboxes)** — `create_ods_client` + `wait_for_sandbox`. - **Metrics** — `create_metrics_client` + `get_overall_metrics`, `get_sales_metrics`, `get_scapi_metrics`, ... - **Logs** — `list_log_files`, `get_recent_logs`; `tail_logs` (async-only). - **Account Manager** — `create_user`, `grant_role`, `list_orgs`, ... - **Raw HTTP** — `instance.ocapi` (OCAPI Data API), `instance.webdav` (`put`/`get`/`delete`/`propfind`). **SCAPI Admin clients** need system auth (client-credentials or JWT) **and** a `short_code` + `tenant_id`. Get the coordinates from `instance.scapi_client_config` (it's `None` when the instance can't do SCAPI): ```python from b2c_tooling_sdk.clients import create_metrics_client, MetricsClientConfig scapi = instance.scapi_client_config if scapi is not None: metrics = create_metrics_client( MetricsClientConfig(short_code=scapi.short_code, tenant_id=scapi.tenant_id), scapi.auth, ) ``` ## 6. SLAS shopper tokens (storefront) For **shopper**-facing storefront tokens (not admin/tooling). Subpath import only — not in the top-level barrel: ```python from b2c_tooling_sdk.slas import get_guest_token, SlasTokenConfig token = await get_guest_token(SlasTokenConfig( short_code="abcd1234", organization_id="f_ecom_zzte_053", slas_client_id="...", site_id="RefArch", redirect_uri="http://localhost:3000/callback", # slas_client_secret="..." # omit for a public PKCE client )) print(token.access_token) # shopper JWT ``` `get_registered_token(SlasRegisteredLoginConfig(...))` for logged-in customers. Blocking twins are in `b2c_tooling_sdk.sync`. The tooling SDK has **no** dedicated storefront client — after minting the token, call Shopper endpoints with plain `httpx` using `token.access_token` as a bearer. ## Runnable examples `python/samples/` has runnable scripts (`code/*_async.py` + `*_sync.py`) and notebooks (`notebook/*.ipynb`) for each scenario above (oauth_ocapi, oauth_scapi, basic_webdav, cli_session, browser_login, slas_shopper, multi_env). Point users there; copy `dw.example.json` → `dw.json` and fill in credentials.
GitHubで見る