Skip to main content

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.


  • 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, each with Shopify Payments connected.
  • A working Shop Pay Wallet integration. To set one up, refer to Get started with Shop Pay Wallet and Sessions and events.
  • Error handling for business entity errors on session creation, business entity updates, and submit. Refer to Handle errors.

  1. You can pass a business entity ID when you create the payment request session with 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 for that business entity.
  3. While the buyer checks out, your backend can change the business entity 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 before you send businessEntityId.


Anchor to Get business entity IDsGet business entity IDs

Use the GraphQL Admin API businessEntities query to list the store's business entities:

Query

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

Response

{
"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.


Anchor to Create a session with a business entityCreate 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:

session.addEventListener("sessionrequested", (ev) => {
// Your backend chooses the business entity and creates the session
fetch('/replace_with_your_endpoint', {
method: 'POST',
body: JSON.stringify({
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 mutation. From version 2026-10, only sourceIdentifier is required and the paymentRequest argument is deprecated, so the example doesn't pass a payment request:

Mutation

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

Input

{
"sourceIdentifier": "xyz123",
"businessEntityId": "gid://shopify/BusinessEntity/1002"
}

Response

{
"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.


Anchor to Change the business entity during checkoutChange 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 mutation from your backend, and wait for it to return before you call the event's complete method:

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

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

Input

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

Response

{
"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.

The 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

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

Response

{
"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.


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 or shopPayPaymentRequestReceipts query:

Query

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

Response

{
"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.


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.

Anchor to Business entity error codesBusiness entity error codes

CodeMeaningWhat to do
BUSINESS_ENTITY_NOT_FOUNDThe 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_ARCHIVEDThe business entity is archived.Unarchive the entity in the Shopify admin, or use a different entity.
BUSINESS_ENTITY_NOT_CHARGEABLEThe 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_SUPPORTEDThe 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 before you send businessEntityId.

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.

Anchor to On a business entity updateOn 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:

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 in Sessions and events.

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:

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.



Was this page helpful?