---
title: Process payments through multiple business entities
description: >-
  Choose which of a merchant's business entities processes each Shop Pay Wallet
  payment, change it during checkout, and reconcile the entity that processed
  it.
source_url:
  html: 'https://shopify.dev/docs/api/commerce-components/pay/multi-entity'
  md: 'https://shopify.dev/docs/api/commerce-components/pay/multi-entity.md'
---

# Process payments through multiple business entities

Merchants that operate through more than one legal entity can process each Shop Pay Wallet payment through the business entity that should own it. The charge, the order, and the payout all belong to that entity's Shopify Payments account. You choose the entity when you create the payment request session, and you can change it while the buyer checks out, for example when the shipping address changes.

***

## Requirements

* Multi-entity is available on the Shop Pay Wallet Enterprise plan.
* Storefront API and GraphQL Admin API version `2027-01` or later. Earlier versions don't include the business entity arguments, fields, mutation, and error codes for payment request sessions and receipts.
* Business entities [added to the store](https://help.shopify.com/en/manual/your-account/business-entities#add-entity), each with [Shopify Payments connected](https://help.shopify.com/en/manual/payments/shopify-payments/onboarding/selling-with-multiple-entities#connect-shopify-payments-to-entity).
* A working Shop Pay Wallet integration. To set one up, refer to [Get started with Shop Pay Wallet](https://shopify.dev/docs/api/commerce-components/pay) and [Sessions and events](https://shopify.dev/docs/api/commerce-components/pay/sessions-and-events).
* Error handling for business entity errors on session creation, business entity updates, and submit. Refer to [Handle errors](#handle-errors).

***

## How it works

1. You can pass a business entity ID when you create the payment request session with [`ShopPayPaymentRequestSessionCreate`](https://shopify.dev/docs/api/commerce-components/pay/graphql-pre-payment#example-shoppaypaymentrequestsessioncreate). If you don't pass one, then the store's primary business entity processes the payment.
2. Shop Pay uses the session's business entity to decide which payment methods are available to the buyer, based on the [payment methods that are active](https://help.shopify.com/en/manual/payments/additional-payment-methods/deactivate-payment-methods) for that business entity.
3. While the buyer checks out, your backend can [change the business entity](https://shopify.dev/docs/api/commerce-components/pay/graphql-pre-payment#example-shoppaypaymentrequestsessionbusinessentityupdate) associated with the session.
4. When you submit the payment, Shopify checks the session's business entity again and records it on the payment request receipt. The charge, the order, and the payout go through that entity's Shopify Payments account.

**Caution:**

Shopify never substitutes the primary business entity for an entity that you chose. If the entity can't process the payment, then the request fails with a business entity error code. If your integration doesn't handle the error, then the buyer can't complete the payment. Implement the error handling in [Handle errors](#handle-errors) before you send `businessEntityId`.

***

## Get business entity IDs

Use the GraphQL Admin API [`businessEntities`](https://shopify.dev/docs/api/admin-graphql/latest/queries/businessEntities) query to list the store's business entities:

## Query

```graphql
query {
  businessEntities {
    id
    displayName
    primary
    archived
    address {
      countryCode
    }
  }
}
```

## Response

```json
{
  "businessEntities": [
    {
      "id": "gid://shopify/BusinessEntity/1001",
      "displayName": "Example Store Inc.",
      "primary": true,
      "archived": false,
      "address": {
        "countryCode": "US"
      }
    },
    {
      "id": "gid://shopify/BusinessEntity/1002",
      "displayName": "Example Store UK Ltd",
      "primary": false,
      "archived": false,
      "address": {
        "countryCode": "GB"
      }
    },
    {
      "id": "gid://shopify/BusinessEntity/1003",
      "displayName": "Example Store Canada Inc.",
      "primary": false,
      "archived": true,
      "address": {
        "countryCode": "CA"
      }
    }
  ]
}
```

The results include archived business entities. An archived entity can't process payments, so leave out every entity where `archived` is `true`.

Keep a mapping in your system from your own routing rule, such as the buyer's shipping country, to the entity's `id`. Pass the full `id` value, such as `gid://shopify/BusinessEntity/1002`, as `businessEntityId`.

A business entity can process payments only when its Shopify Payments account is enabled and can accept charges, Shop Pay is active on it, and it has at least one active payment method.

Don't query `businessEntities` for every checkout. The result changes only when the merchant adds or changes a business entity in the Shopify admin, so querying it on each transaction returns the same data and adds latency to your checkout. Read the entity from your mapping instead, and refresh the mapping after the merchant adds or changes an entity in the Shopify admin, or after a request fails with a business entity error code.

***

## Create a session with a business entity

In the `sessionrequested` listener, send your backend whatever it needs to choose the business entity, such as the country of the storefront that the buyer is on:

```javascript
session.addEventListener("sessionrequested", (ev) => {
  // Your backend chooses the business entity and creates the session
  fetch('/replace_with_your_endpoint', {
    method: 'POST',
    body: JSON.stringify({
      payment_request: initialPaymentRequest,
      storefront_country: 'GB',
    }),
    headers: {
      'Content-Type': 'application/json',
    },
  }).then(response => response.json()).then(data => {
    const {token, checkoutUrl, sourceIdentifier} = data;
    session.completeSessionRequest({token, checkoutUrl, sourceIdentifier});
  });
});
```

On your backend, pass the entity's ID as `businessEntityId` to the [`ShopPayPaymentRequestSessionCreate`](https://shopify.dev/docs/api/commerce-components/pay/graphql-pre-payment#example-shoppaypaymentrequestsessioncreate) mutation:

## Mutation

```graphql
mutation shopPayPaymentRequestSessionCreate($sourceIdentifier: String!, $paymentRequest: ShopPayPaymentRequestInput!, $businessEntityId: String) {
  shopPayPaymentRequestSessionCreate(sourceIdentifier: $sourceIdentifier, paymentRequest: $paymentRequest, businessEntityId: $businessEntityId) {
    shopPayPaymentRequestSession {
      token
      sourceIdentifier
      checkoutUrl
      businessEntityId
    }
    userErrors {
      field
      code
      message
    }
  }
}
```

## Input

```json
{
  "sourceIdentifier": "xyz123",
  "paymentRequest": {
    // …
  },
  "businessEntityId": "gid://shopify/BusinessEntity/1002"
}
```

## Response

```json
{
  "shopPayPaymentRequestSessionCreate": {
    "shopPayPaymentRequestSession": {
      "token": "db4eede13822684b13a607823b7ba40d",
      "sourceIdentifier": "xyz123",
      "checkoutUrl": "https://shop.app/checkout/1/spe/db4eede13822684b13a607823b7ba40d/shoppay",
      "businessEntityId": "gid://shopify/BusinessEntity/1002"
    },
    "userErrors": []
  }
}
```

**Primary business entity:**

Omit `businessEntityId` to process the payment through the primary business entity. Integrations that don't provide it continue to process payments through the primary business entity, as they did before.

If the business entity can't process payments, then Shopify doesn't create the session. Refer to [On session creation](#on-session-creation).

***

## Change the business entity during checkout

If the right business entity depends on something the buyer chooses in the Shop Pay checkout, such as the shipping address, then change the session's entity while handling the event that triggers the change. Call the [`ShopPayPaymentRequestSessionBusinessEntityUpdate`](https://shopify.dev/docs/api/commerce-components/pay/graphql-pre-payment#example-shoppaypaymentrequestsessionbusinessentityupdate) mutation from your backend, and wait for it to return before you call the event's complete method:

```javascript
session.addEventListener("shippingaddresschanged", (ev) => {
  const currentPaymentRequest = session.paymentRequest;
  const shippingAddress = ev.shippingAddress;


  // Your backend chooses the business entity for this address, updates the
  // session if the entity changed, and returns the delivery methods
  fetch('/replace_with_your_endpoint', {
    method: 'POST',
    body: JSON.stringify({
      token: session.token,
      shipping_address: shippingAddress,
    }),
    headers: {
      'Content-Type': 'application/json',
    },
  }).then(response => response.json()).then(data => {
    const {deliveryMethods} = data;


    const updatedPaymentRequest = window.ShopPay.PaymentRequest.build({
      ...currentPaymentRequest,
      deliveryMethods,
    });


    session.completeShippingAddressChange({ updatedPaymentRequest: updatedPaymentRequest });
  });
});
```

On your backend, pass the session token and the new entity's ID:

## Mutation

```graphql
mutation shopPayPaymentRequestSessionBusinessEntityUpdate($token: String!, $businessEntityId: String!) {
  shopPayPaymentRequestSessionBusinessEntityUpdate(token: $token, businessEntityId: $businessEntityId) {
    shopPayPaymentRequestSession {
      token
      businessEntityId
    }
    userErrors {
      field
      code
      message
    }
  }
}
```

## Input

```json
{
  "token": "db4eede13822684b13a607823b7ba40d",
  "businessEntityId": "gid://shopify/BusinessEntity/1001"
}
```

## Response

```json
{
  "shopPayPaymentRequestSessionBusinessEntityUpdate": {
    "shopPayPaymentRequestSession": {
      "token": "db4eede13822684b13a607823b7ba40d",
      "businessEntityId": "gid://shopify/BusinessEntity/1001"
    },
    "userErrors": []
  }
}
```

When you change the business entity, keep the following in mind:

* Update the entity before you call the complete method for the event, so that Shopify applies the new entity to the checkout.
* `businessEntityId` is required on this mutation. To move the session back to the primary business entity, pass the primary entity's ID.
* You can change the entity until you submit the payment. If a payment attempt fails, then you can change it again before the buyer retries.

***

## Submit the payment

The [`ShopPayPaymentRequestSessionSubmit`](https://shopify.dev/docs/api/commerce-components/pay/graphql-pre-payment#example-shoppaypaymentrequestsessionsubmit) mutation doesn't take a business entity. Shopify reads the entity from the session, checks it again, and records it on the payment request receipt. Request `businessEntityId` on the receipt to confirm the entity that processes the payment:

## Mutation

```graphql
mutation shopPayPaymentRequestSessionSubmit($token: String!, $paymentRequest: ShopPayPaymentRequestInput!, $idempotencyKey: String!) {
  shopPayPaymentRequestSessionSubmit(token: $token, paymentRequest: $paymentRequest, idempotencyKey: $idempotencyKey) {
    paymentRequestReceipt {
      token
      processingStatusType
      businessEntityId
    }
    userErrors {
      field
      code
      message
    }
  }
}
```

## Response

```json
{
  "shopPayPaymentRequestSessionSubmit": {
    "paymentRequestReceipt": {
      "token": "a607823b7ba40ddb4eede13822684b13",
      "processingStatusType": "ready",
      "businessEntityId": "gid://shopify/BusinessEntity/1001"
    },
    "userErrors": []
  }
}
```

If the business entity can no longer process payments, for example if the entity was archived after the session was created, then the submit fails and Shopify doesn't create a receipt. Refer to [On submit](#on-submit).

***

## Reconcile orders

The payment request receipt records the business entity that the charge, the order, and the payout went through. In your reconciliation job, request `businessEntity` on the GraphQL Admin API [`shopPayPaymentRequestReceipt`](https://shopify.dev/docs/api/admin-graphql/2027-01/queries/shopPayPaymentRequestReceipt) or [`shopPayPaymentRequestReceipts`](https://shopify.dev/docs/api/admin-graphql/2027-01/queries/shopPayPaymentRequestReceipts) query:

## Query

```graphql
query {
  shopPayPaymentRequestReceipt(token: "a607823b7ba40ddb4eede13822684b13") {
    token
    sourceIdentifier
    processingStatus {
      state
    }
    businessEntity {
      id
      displayName
      archived
    }
    order {
      id
    }
  }
}
```

## Response

```json
{
  "shopPayPaymentRequestReceipt": {
    "token": "a607823b7ba40ddb4eede13822684b13",
    "sourceIdentifier": "xyz123",
    "processingStatus": {
      "state": "COMPLETED"
    },
    "businessEntity": {
      "id": "gid://shopify/BusinessEntity/1001",
      "displayName": "Example Store Inc.",
      "archived": false
    },
    "order": {
      "id": "gid://shopify/Order/1"
    }
  }
}
```

`businessEntity` also returns archived entities, so an order stays attributed to the entity that took the payment after the merchant archives it. For the rest of the reconciliation flow, refer to [Monitoring and resiliency](https://shopify.dev/docs/api/commerce-components/pay/monitoring#reconciliation-job).

***

## Handle errors

Your integration is responsible for handling business entity errors. Shopify doesn't retry with a different entity, so decide what your checkout does when an entity can't process a payment, such as creating the session again with a different entity, or showing the buyer a message and stopping the checkout.

Shopify returns business entity errors in `userErrors`. Request `code` in every `userErrors` selection, and use it to decide what to do next.

### Business entity error codes

| Code | Meaning | What to do |
| - | - | - |
| `BUSINESS_ENTITY_NOT_FOUND` | The ID doesn't match a business entity on this store, or it isn't a full business entity ID such as `gid://shopify/BusinessEntity/1002`. | Query `businessEntities` again and update your mapping. |
| `BUSINESS_ENTITY_ARCHIVED` | The business entity is archived. | Unarchive the entity in the Shopify admin, or use a different entity. |
| `BUSINESS_ENTITY_NOT_CHARGEABLE` | The business entity can't accept payments. Its Shopify Payments account isn't enabled or can't accept charges, Shop Pay isn't active on it, or it has no active payment method. | Complete the entity's Shopify Payments setup in the Shopify admin, or use a different entity. |
| `MULTI_ENTITY_NOT_SUPPORTED` | The store isn't set up to process payments through multiple business entities, so it can't use the business entity that you passed. | Check that the store meets the [requirements](#requirements) before you send `businessEntityId`. |

### On session creation

The error's `field` is `["businessEntityId"]`, and Shopify doesn't create a session. You don't get a `token` to pass to `completeSessionRequest()`, so close the Shop Pay dialog with `session.close()` and handle the failure in your own checkout. Your system decides whether to create the session again with a different entity, because Shopify doesn't fall back to the primary entity.

### On a business entity update

The error's `field` is `["businessEntityId"]`, and the session keeps its previous business entity. If the buyer can't pay through the previous entity for their new choice, then reject the change in the complete call. For example, return a `shippingAddressError` for a shipping address that no business entity can process:

```javascript
session.addEventListener("shippingaddresschanged", (ev) => {
  const currentPaymentRequest = session.paymentRequest;


  // Your backend returns businessEntityError when the update fails
  fetch('/replace_with_your_endpoint', {
    method: 'POST',
    body: JSON.stringify({
      token: session.token,
      shipping_address: ev.shippingAddress,
    }),
    headers: {
      'Content-Type': 'application/json',
    },
  }).then(response => response.json()).then(data => {
    const {businessEntityError} = data;


    if (businessEntityError) {
      session.completeShippingAddressChange({
        updatedPaymentRequest: window.ShopPay.PaymentRequest.build({
          ...currentPaymentRequest,
          deliveryMethods: [],
        }),
        errors: [
          {
            type: "shippingAddressError",
            message: "We can't ship to this address. Select a different address.",
          }
        ]
      });
      return;
    }


    // Otherwise, complete the change with the delivery methods for this address
  });
});
```

The update mutation can also return the following codes on the `token` field:

* `PAYMENT_REQUEST_NOT_FOUND`: the token doesn't match a payment request session on this store.
* `PAYMENT_REQUEST_SESSION_ALREADY_SUBMITTED`: you already submitted the payment and the attempt hasn't failed, so the business entity can't change. Create a new session for another payment attempt.

For more ways to return errors from a complete call, refer to [Handle errors](https://shopify.dev/docs/api/commerce-components/pay/sessions-and-events#handle-errors) in Sessions and events.

### On submit

The error's `field` is `null`, and Shopify doesn't create a receipt. The session's business entity was valid when you selected it, but its state changed before you submitted the payment.

Return a `generalError` from `completePaymentConfirmationRequest()` so that the buyer stays in the Shop Pay dialog:

```javascript
session.completePaymentConfirmationRequest({
  errors: [
    {
      type: "generalError",
      message: "We couldn't process your payment. Try again.",
    }
  ]
});
```

Before the buyer tries again, move the session to a business entity that can process payments with `ShopPayPaymentRequestSessionBusinessEntityUpdate`. `MULTI_ENTITY_NOT_SUPPORTED` on submit means that the store stopped using multiple business entities after you created the session, so your system decides how to handle the checkout.

***

## Next steps

[Sessions and events\
\
](https://shopify.dev/docs/api/commerce-components/pay/sessions-and-events)

[Create payment request sessions and handle checkout events.](https://shopify.dev/docs/api/commerce-components/pay/sessions-and-events)

[GraphQL pre-payment\
\
](https://shopify.dev/docs/api/commerce-components/pay/graphql-pre-payment)

[Create, update, and submit payment request sessions using the Storefront API.](https://shopify.dev/docs/api/commerce-components/pay/graphql-pre-payment)

[Monitoring and resiliency\
\
](https://shopify.dev/docs/api/commerce-components/pay/monitoring)

[Set up webhooks, handle disputes, and implement reconciliation.](https://shopify.dev/docs/api/commerce-components/pay/monitoring)

***
