> ## Documentation Index
> Fetch the complete documentation index at: https://docs.global-e.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Commerce API support (OCAPI, SCAPI)

The cartridge repository includes **`int_globale_headless`**, which enables Global-e on **headless** storefronts — PWA, mobile apps, or any client that renders pages itself and talks to SFCC through the Shop **OCAPI** (Open Commerce API) or **SCAPI** (B2C Commerce API).

<Note>
  This is an optional feature for headless architectures. It requires additional cartridges, hook clean-up, and PWA-side implementation. See [Configuration](#configuration).
</Note>

## Configuration

### Cartridge path

Add three cartridges to the SFCC cartridge path:

* **SiteGenesis architecture:** `int_globale_headless`, `int_globale_sitegenesis`, `int_globale`
* **SFRA architecture:** `int_globale_headless`, `int_globale_sfra`, `int_globale`

### Hook handlers

The headless OCAPI handlers ship in `int_globale_headless`, so remove the duplicates from the storefront cartridge:

* **SiteGenesis:** remove `coupon.js`, `order.js`, `basket.js` from `int_globale_sitegenesis` (they also exist in `int_globale_headless`).
* **SFRA:** remove `coupon.js`, `order.js`, `basket.js` from `int_globale_sfra`.

If the headless approach is used for **all** storefront pages, also remove the overridden base-cartridge templates from `int_globale_sitegenesis` / `int_globale_sfra`. If you run a **hybrid** strategy (for example, headless everywhere except checkout, which stays on SFRA/SiteGenesis), keep those overridden templates.

<Note>
  **Important:** enable hook execution for Commerce API requests.
  **Administration → Global Preferences → Feature Switches → Enable Salesforce Commerce API Hook Execution.**
</Note>

The full list of headless platform hooks is in the [Hooks reference](/hooks-sfcc#headless-int_globale_headless).

### Site preferences

Configure these regardless of which API you use, in the **Global-e Settings** group:

* `geEnableCartValidationCAPIBasket`
* `geCAPIType` (OCAPI or SCAPI)

If you use **OCAPI**, configure the **Global-e OCAPI Settings** group:

* `geOCAPIDomain`, `geOCAPIVersion`, `geOCAPIClientId`

If you use **SCAPI**, configure the **Global-e SCAPI Settings** group:

* `geSCAPIOrganizationId`, `geSCAPIShortCode`, `geSCAPIVersion`, `geSCAPIRedirectURI`, `geSCAPIAuthType`, `geSCAPIClientId`, `geSCAPIClientSecret`

See [Configuration](/configuration-sfcc) for the full site-preference walkthrough.

### Open Commerce API (OCAPI) settings

Configure the OCAPI Shop API JSON in Business Manager to cover the resources Global-e may use. Extend it to match your project's needs.

```json theme={null}
{
    "_v": "**.*",
    "clients": [
        {
            "client_id": "<your-client-id>",
            "resources": [
                { "resource_id": "/baskets", "methods": ["post"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/baskets/*", "methods": ["get", "patch", "delete"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/baskets/*/coupons", "methods": ["post"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/baskets/*/coupons/*", "methods": ["delete"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/baskets/*/items", "methods": ["post"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/baskets/*/items/*", "methods": ["delete", "patch"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/orders", "methods": ["post"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/orders/*", "methods": ["get", "patch"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/customers", "methods": ["post"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/customers/auth", "methods": ["post", "delete"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/customers/*", "methods": ["get", "patch"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/customers/*/auth", "methods": ["post"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/customers/*/baskets", "methods": ["get"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/product_search", "methods": ["get"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/products/*", "methods": ["get"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/sessions", "methods": ["post"], "read_attributes": "(**)", "write_attributes": "(**)" },
                { "resource_id": "/custom_objects/*/*", "methods": ["get"], "read_attributes": "(**)", "write_attributes": "(**)" }
            ]
        }
    ]
}
```

> **Important (SCAPI):** even when you integrate through SCAPI, you must still allow the `/sessions` resource via OCAPI, because Global-e uses it. You can reuse the same client ID as your other SCAPI requests — a separate client ID is not required.
>
> ```json theme={null}
> {
>     "_v": "**.*",
>     "clients": [
>         {
>             "client_id": "<your-scapi-client-id>",
>             "resources": [
>                 { "resource_id": "/sessions", "methods": ["post"], "read_attributes": "(**)", "write_attributes": "(**)" }
>             ]
>         }
>     ]
> }
> ```

## Global-e checkout on a headless storefront

On headless, the Global-e checkout page is initialized and shown the same way as on the classic web storefront.

<Note>
  **Important:** if the shopper reaches the checkout but the SFCC basket is invalid (no product line items, or no total price), SFCC does **not** send the SendCart data to Global-e, and the basket custom attribute `c_geCartToken` is null or absent in the PATCH basket response. The PWA must handle this — for example by redirecting the shopper to the cart page.
</Note>

### 1. Get the Global-e cart token

Send a PATCH basket request with the query parameter `c_geGetCartToken`. Send it **once**, after all other basket requests are complete and just before the checkout page is shown. SFCC then sends the **SendCart** data to Global-e and stores the returned cart token in the basket custom attribute `c_geCartToken` (visible in the PATCH response).

### 2. Initialize the Global-e client SDK

Initializing the SDK requires:

* `clientJsUrl` — the client JS URL (composed of `clientJsBaseUrl` + `clientJsSource`)
* `apiVersion` — the API version from the Global-e session
* `clientJsMerchantId` — the merchant ID from preferences
* `clientSettings` — client-specific settings
* `clientJsDomain` — the client JS base URL
* `cookieDomain` — the domain for Global-e cookies (defined on the PWA/app side)

All of these except `cookieDomain` can be retrieved by requesting the `GLOBALE_APP_SETTINGS` custom object with the query parameter `c_geGetSDKInitData`.

The headless cartridge provides the Global-e client-side JS at `int_globale_headless/cartridge/client/default/js/globaleClientScripts.js`, which the headless storefront can reuse.

### 3. Render the checkout

Once the cart token is available and the SDK is initialized, use the token to show the Global-e checkout in an iframe. Add an empty `<div id="gle_iframe">` to the checkout template — it becomes the iframe wrapper.

### Checkout confirmation and hosted payment pages

The Global-e checkout supports two kinds of payment methods:

* **Without a hosted payment page** (for example credit/debit cards): on **Place Order**, the checkout refreshes **inside the iframe** (the browser page does not reload) and the shopper sees the confirmation page.
* **With a hosted payment page** (for example PayPal): the shopper is redirected to the provider's page, completes payment, and is redirected back to the storefront. On return, the existing cart token is provided in the URL as the `token` query parameter — the storefront must re-initialize checkout from that token.

Out of the box, SiteGenesis and SFRA handle this redirect flow. **Headless storefronts must implement it.**

#### Handling the payment redirect (headless)

Shoppers sometimes complete payment but are not returned to the confirmation page (for example, session loss in Safari Private Browsing, in-app WebViews, or 3DS redirects can drop the cart token). To handle it reliably:

<Steps>
  <Step>
    **Persist the cart token** — after each successful SendCart, save the cart token in a browser cookie and update it on every SendCart.
  </Step>

  <Step>
    **Add a dedicated endpoint** — implement a headless endpoint for the redirect scenario, initializing the SDK the same way as the checkout endpoint.
  </Step>

  <Step>
    **Resolve the cart token** — when the endpoint is hit, use the `token` URL parameter if present; otherwise fall back to the cart token in the cookie.
  </Step>

  <Step>
    **Show the confirmation page** — initialize the SDK with the resolved token and render the confirmation page.
  </Step>
</Steps>

### Helper tools (Postman)

Postman environments and collections are available for developing and testing the headless integration (authorize a customer, create/modify a basket, apply coupons, work with products, get a cart token, and so on). Request these from **Global-e Merchant Support**.

## See also

* [Configuration](/configuration-sfcc) — `geCAPIType` and OCAPI/SCAPI preferences
* [Cartridges](/cartridges-sfcc) · [Installation](/installation-sfcc)
* [Headless hooks](/hooks-sfcc#headless-int_globale_headless)
* [Client JS SDK](/client-js-sdk-sfcc)
