SfSkills Domains Docs GitHub

Home / apex / commerce-order-api

commerce-order-api

Use this skill when building or debugging headless B2C Commerce storefront order submission using the Salesforce Commerce API (SCAPI) ShopAPI Orders endpoint or the legacy OCAPI /orders resource — order creation, SLAS authentication for shopper order access, order amendment, order status retrieval, and order-event notifications and webhooks. NOT for OrderSummary, FulfillmentOrder, or other OMS Connect API work — use admin/commerce-order-management. NOT for shopper login, basket, or checkout calls — use apex/headless-commerce-api.

Open the skill folder on GitHub


Commerce Order API (SCAPI / OCAPI — Headless Storefront)

This skill activates when a practitioner needs to submit, retrieve, or manage orders from a headless B2C Commerce storefront using the Salesforce Commerce API (SCAPI) or its predecessor OCAPI. It covers the shopper-facing API layer: authenticating shoppers via SLAS, placing orders against an active basket, retrieving order status and history, and wiring order notifications. It does NOT cover the OMS Connect API layer (OrderSummary, FulfillmentOrder, submit-cancel, ensure-funds-async) — that is handled by admin/commerce-order-management.


Before Starting

Gather this context before working on anything in this domain:


Core Concepts

SCAPI ShopAPI Orders — The Modern Path

The Salesforce Commerce API (SCAPI) ShopAPI Orders resource is the current standard for headless order submission:

AspectDetails
EndpointPOST /checkout/shopper-orders/v1/organizations/{organizationId}/orders
AuthSLAS Bearer token in the Authorization header. Guest shoppers use a SLAS guest token; registered shoppers use a SLAS registered (JWT) token obtained via PKCE or client credentials flow.
Input stateThe request body contains only {"basketId": "<uuid>"}. The shopper must have previously built a basket via the Shopper Baskets API. All product, price, shipping, and payment data is read from the basket at submit time.
OutputA full Order representation including orderNo, status (created), payment_status, confirmation_status, line items, shipments, and applied promotions. The basket is atomically deleted.
IdempotencyNOT idempotent. Retrying a POST /orders after a network timeout can create a duplicate order if the first call succeeded. Implement client-side dedup using a client-generated basket ID check before retrying.

SLAS Scopes for Orders:

OperationRequired Scope
Place order (guest or registered)sfcc.shopper-baskets-orders
Get order detailssfcc.shopper-baskets-orders
Get shopper order historysfcc.shopper-myaccount.order
Guest order lookup (by email + orderNo)sfcc.shopper-orders (public client)

OCAPI Shop API Orders — The Legacy Path

OCAPI (/s/{site-id}/dw/shop/v23_2/orders) remains available for existing integrations but is in maintenance mode. Key behavioral differences from SCAPI:

SLAS Authentication for Order Submission

SLAS (Shopper Login and API Access Service) is mandatory for SCAPI order submission. It is hosted separately from the core Salesforce platform and operates through Account Manager:

Order Status and Notifications

B2C Commerce headless does not push order status changes via native Salesforce Platform Events. Order status notifications use one of two mechanisms:

  1. B2C Commerce Hooks (dw.system.HookMgr): A custom cartridge can register a hook on dw.order.afterOrderCreated or dw.order.afterOrderStatusChange. The hook script runs server-side in the Commerce Cloud cartridge layer and can fire an HTTP callout to an external webhook or a Salesforce Experience Cloud endpoint.
  2. Order Management Platform Events (after OMS integration): Once a B2C order is ingested into OMS as an OrderSummary, OrderSummaryCreatedEvent, FOStatusChangedEvent, and OrderSumStatusChangedEvent platform events carry status changes back to Salesforce core. This requires the OMS integration layer and is described in admin/commerce-order-management.

For pure headless storefronts without OMS, polling GET /orders/{orderNo} is the fallback for order status — it is not a webhook model.


Common Patterns

Pattern: Guest Shopper Order Submission via SCAPI

When to use: A headless storefront (React, Vue, mobile) needs to place an order for an anonymous/guest shopper.

How it works:

  1. Obtain a SLAS guest token:
    POST https://{shortCode}.api.commercecloud.salesforce.com/shopper/auth/v1/organizations/{organizationId}/oauth2/guest/token
    Body: grant_type=client_credentials&client_id={publicClientId}
  2. Create a basket via Shopper Baskets API (POST /baskets). Add product line items, set shipping address and method, add payment instrument.
  3. Submit the order:
    POST /checkout/shopper-orders/v1/organizations/{organizationId}/orders
    Authorization: Bearer {slasGuestToken}
    Body: {"basketId": "{basketId}"}
  4. Parse the response orderNo and status. Store orderNo in local state — it is the only future lookup key for guest shoppers.
  5. Trigger confirmation email via cartridge hook or external service using orderNo.

Why not the alternative: Using OCAPI for new guest order placement requires configuring OCAPI client settings in Business Manager per-site and does not benefit from SLAS centralized token management or the newer Commerce API rate-limiting and observability tooling.

Pattern: Registered Shopper Order History Retrieval

When to use: A logged-in shopper views their order history in a headless My Account page.

How it works:

  1. Obtain a SLAS registered token for the shopper (PKCE flow or session-based via trusted agent).
  2. Call:
    GET /checkout/shopper-orders/v1/organizations/{organizationId}/orders?offset=0&limit=10
    Authorization: Bearer {registeredToken}
  3. The response is paginated. Use total, offset, and limit in the response envelope for pagination. Filter by status query param if needed (created, new, open, completed, cancelled).
  4. For order detail, call GET /orders/{orderNo} with the same registered token.

Why not the alternative: Guest tokens cannot access GET /orders — the API returns 403. Attempting to look up a registered shopper's order history with a guest token is the most common auth mistake in headless implementations.

Pattern: Apex Callout to Read B2C Order Data into Salesforce Core

When to use: A Salesforce core org needs to read order data from B2C Commerce (e.g., to display recent orders in Service Console) without OMS integration.

How it works:

  1. Use the SLAS Trusted Agent flow in Apex to obtain a server-side access token (no browser required):
    HttpRequest req = new HttpRequest();
    req.setEndpoint('callout:SLAS_Endpoint/shopper/auth/v1/organizations/{orgId}/oauth2/token');
    req.setMethod('POST');
    req.setBody('grant_type=client_credentials&client_id={privateClientId}&client_secret={secret}');
  2. Store the token in a custom setting or Platform Cache (not in a field on a record — avoid token persistence in audit-visible storage).
  3. Use the token in a subsequent callout to GET /orders/{orderNo} or GET /orders and map the response to a Salesforce object or LWC display component.

Why not the alternative: Hardcoding an OCAPI client secret in Apex Named Credentials or Custom Metadata without rotating expiry logic creates a credential exposure risk and makes the integration fragile when OCAPI clients are regenerated in Business Manager.


Decision Guidance

SituationRecommended ApproachReason
New headless storefront, order submissionSCAPI ShopAPI Orders + SLASStrategic API; modern token management; no per-site OCAPI configuration required
Existing OCAPI integration, maintenance modeKeep OCAPI until migration window; plan SCAPI migrationOCAPI is not yet sunset, but no new features; plan migration per Salesforce roadmap
Guest shopper order placementSLAS guest token + SCAPI POST /ordersGuest tokens work; registered token not required for submission
Registered shopper order historySLAS registered token (PKCE) + SCAPI GET /ordersGuest tokens cannot access order history; registered token is mandatory
Order amendments after submissionOMS Connect API (admin/commerce-order-management)SCAPI ShopAPI has no amendment endpoint; all post-submission changes go through OMS
Order confirmation emailB2C Commerce Hook (dw.order.afterOrderCreated)Runs in cartridge layer at order creation time; native to Commerce Cloud
Reading B2C order data into Salesforce coreSLAS Trusted Agent + Apex calloutAvoids browser PKCE in server-side context; secure client credentials flow
Order status webhooks without OMSB2C Hooks + external HTTP calloutCommerce Cloud has no native push webhook; hooks fire server-side callouts

Step-by-step instructions for an AI agent or practitioner working on this task:

  1. Confirm API path (SCAPI vs OCAPI): Determine whether this is a new integration (use SCAPI) or a maintained legacy integration (OCAPI). For SCAPI, confirm the org's shortCode and organizationId from the Commerce Cloud Business Manager (Administration > Salesforce Commerce API Settings). For OCAPI, locate the site-level OCAPI Shop API settings in Business Manager.
  2. Configure SLAS: In Account Manager, verify a SLAS client exists with sfcc.shopper-baskets-orders scope and the storefront's redirect URI. For server-side Apex callouts, configure a private SLAS client and store credentials in Salesforce Named Credentials — never in Apex source or Custom Metadata readable by all profiles.
  3. Implement the basket-to-order flow: Build the shopper basket using the Shopper Baskets API before calling the Orders endpoint. Validate the basket is complete (shipping address, shipping method, payment instrument) before submission. The Orders endpoint will reject an incomplete basket with a 400 error.
  4. Submit the order and handle the response: Call POST /checkout/shopper-orders/v1/.../orders with the basketId. Parse orderNo and status from the response. Implement client-side deduplication: do not retry a POST /orders without first confirming via GET /orders/{orderNo} that the order does not already exist.
  5. Wire notifications: Implement a B2C Commerce cartridge hook on dw.order.afterOrderCreated for immediate post-submission notifications. For status change notifications, implement a hook on dw.order.afterOrderStatusChange or integrate with OMS platform events if the org uses OMS.
  6. Test authentication edge cases: Verify that expired SLAS tokens return 401 and the client refreshes correctly. Test guest shopper order lookup using orderNo + email (not session token). Test that registered shopper order history returns correct results and pagination works at the 10-record boundary.
  7. Review security posture: Confirm SLAS client secrets are not exposed in browser-accessible JavaScript (use private SLAS clients only in server-side code). Confirm Named Credentials are used for Apex callouts. Confirm OCAPI allowed-origins whitelist is restricted to known storefront domains if OCAPI is in use.

Review Checklist

Run through these before marking work in this area complete:


Salesforce-Specific Gotchas

Non-obvious platform behaviors that cause real production problems:

  1. POST /orders is not idempotent and basket is destroyed on success — A network timeout during order submission leaves the client uncertain: did the order succeed? The basket is deleted on success. Retrying POST /orders creates a duplicate order. The safe recovery pattern is to call GET /orders?basketId={basketId} (OCAPI) or check order history by other means before retrying. Design the storefront to show a "checking order status" state before offering a retry button.
  2. SLAS scope mismatches produce 403 with no useful error body — If the SLAS client lacks sfcc.shopper-baskets-orders, the orders endpoint returns a 403 with a generic payload. Business Manager does not surface scope errors in request logs by default. Always verify scopes in Account Manager before debugging storefront code.
  3. Guest tokens cannot retrieve order history — 403, not 401 — Developers often mistake a guest-authenticated GET /orders 403 for a token expiry or scope issue. The distinction matters: 401 means re-authenticate; 403 means the token is valid but lacks privilege. For guest order lookup, use the OCAPI GET /orders/{orderNo}?guest_email={email} pattern or implement a dedicated guest order lookup endpoint.
  4. OCAPI and SCAPI use different key casing conventions — OCAPI response keys are snake_case (customer_info, billing_address); SCAPI response keys are camelCase (customerInfo, billingAddress). Code that handles both APIs without an adapter layer will produce silent null-reference bugs in JavaScript when the casing assumption is wrong.
  5. SCAPI has no order amendment endpoint — amendments require OMS — After a SCAPI order is submitted, the ShopAPI has no PATCH /orders/{orderNo} equivalent. Any quantity change, address correction, or cancellation requires either the OMS Connect API actions (if OMS is integrated) or a custom cartridge solution with direct business object access. Teams that discover this limitation post-launch often attempt direct DML against OMS objects, which corrupts financial aggregates in MANAGED mode.

Output Artifacts

ArtifactDescription
SCAPI order submission responseJSON with orderNo, status, paymentStatus, confirmationStatus, lineItems, shipments
SLAS token configurationAccount Manager client configuration with scopes for guest and registered order flows
B2C Commerce hook registrationCartridge hook script wired to dw.order.afterOrderCreated for order notifications
Order history API responsePaginated list of order summaries for registered shoppers via GET /orders
Named Credential configurationSalesforce Named Credential for Apex callout to SCAPI with SLAS Trusted Agent auth


Official Sources Used

Package files