A Merchant API region represents a geographic region that you can use as a
target related to the `accounts.products.regionalInventories` resource. You can
define regions as collections of either postal codes or, in some countries,
using predefined geotargets. For more information, see [Set up
regions](https://support.google.com/merchants/answer/15406457#zippy=%2Ccreate-a-new-regionS).

Merchant API provides batch endpoints for managing your regions, allowing you to
create, update, and delete up to **100** regions in a single API call. This is
ideal for merchants managing regional availability and pricing (RAAP) at scale,
improving efficiency and simplifying integration.

## Overview

Batch API lets you accomplish the following with the associated methods:

- **Create multiple regions** in a single request: `regions:batchCreate`
- **Delete multiple regions** at once: `regions:batchDelete`
- **Update multiple regions** simultaneously: `regions:batchUpdate`

## Prerequisites

All batch requests require the **ADMIN** user role for authentication.

## Create multiple regions

This example shows how to create two new regions --- one defined by postal codes
and another by geo targeting --- in a single call of `BatchCreateRegions`.

### Request

Construct the request URL as follows:

    POST
    https://merchantapi.googleapis.com/accounts/v1/accounts/{ACCOUNT_ID}/regions:batchCreate

The request body contains a list of `requests`, where each object specifies a
`regionId` and the `region` data to create.

    {
      "requests": [
        {
          "regionId": "seattle-area-98340",
          "region": {
            "displayName": "Seattle Region",
            "postalCodeArea": {
              "regionCode": "US",
              "postalCodes": [
                {
                  "begin": "98340"
                }
              ]
            }
          }
        },
        {
          "regionId": "co-de-states",
          "region": {
            "displayName": "Colorado and Delaware",
            "geoTargetArea": {
              "geotargetCriteriaIds": [
                "21138",
                "21141"
              ]
            }
          }
        }
      ]
    }

### Response

A successful request returns a list of the new `region` objects.

    {
      "regions": [
        {
          "name": "accounts/{ACCOUNT_ID}/regions/seattle-area-98340",
          "displayName": "Seattle Region",
          "postalCodeArea": {
            "regionCode": "US",
            "postalCodes": [
              {
                "begin": "98340"
              }
            ]
          },
          "regionalInventoryEligible": true,
          "shippingEligible": true
        },
        {
          "name": "accounts/{ACCOUNT_ID}/regions/co-de-states",
          "displayName": "Colorado and Delaware",
          "geotargetArea": {
            "geotargetCriteriaIds": [
              "21138",
              "21141"
            ]
          },
          "regionalInventoryEligible": false,
          "shippingEligible": false
        }
      ]
    }

The following sample demonstrates how to create multiple regions in a batch
request:

### Java

    import com.google.api.gax.core.FixedCredentialsProvider;
    import com.google.auth.oauth2.GoogleCredentials;
    import com.google.shopping.merchant.accounts.v1.BatchCreateRegionsRequest;
    import com.google.shopping.merchant.accounts.v1.BatchCreateRegionsResponse;
    import com.google.shopping.merchant.accounts.v1.CreateRegionRequest;
    import com.google.shopping.merchant.accounts.v1.Region;
    import com.google.shopping.merchant.accounts.v1.Region.PostalCodeArea;
    import com.google.shopping.merchant.accounts.v1.Region.PostalCodeArea.PostalCodeRange;
    import com.google.shopping.merchant.accounts.v1.RegionsServiceClient;
    import com.google.shopping.merchant.accounts.v1.RegionsServiceSettings;
    import java.util.ArrayList;
    import java.util.List;
    import shopping.merchant.samples.utils.Authenticator;
    import shopping.merchant.samples.utils.Config;

    /** This class demonstrates how to create multiple regions for a Merchant Center account. */
    public class BatchCreateRegionsSample {

      private static String getParent(String accountId) {
        return String.format("accounts/%s", accountId);
      }

      public static void batchCreateRegions(Config config, List<String> regionIds) throws Exception {

        // Obtains OAuth token based on the user's configuration.
        GoogleCredentials credential = new Authenticator().authenticate();

        // Creates service settings using the credentials retrieved above.
        RegionsServiceSettings regionsServiceSettings =
            RegionsServiceSettings.newBuilder()
                .setCredentialsProvider(FixedCredentialsProvider.create(credential))
                .build();

        // Creates parent to identify where to insert the regions.
        String parent = getParent(config.getAccountId().toString());

        // Calls the API and catches and prints any network failures/errors.
        try (RegionsServiceClient regionsServiceClient =
            RegionsServiceClient.create(regionsServiceSettings)) {

          List<CreateRegionRequest> requests = new ArrayList<>();
          for (String regionId : regionIds) {
            requests.add(
                CreateRegionRequest.newBuilder()
                    .setParent(parent)
                    .setRegionId(regionId)
                    .setRegion(
                        Region.newBuilder()
                            .setDisplayName("Region " + regionId)
                            .setPostalCodeArea(
                                PostalCodeArea.newBuilder()
                                    .setRegionCode("US")
                                    .addPostalCodes(
                                        PostalCodeRange.newBuilder()
                                            .setBegin("10001")
                                            .setEnd("10282")
                                            .build())
                                    .build())
                            .build())
                    .build());
          }

          BatchCreateRegionsRequest request =
              BatchCreateRegionsRequest.newBuilder().setParent(parent).addAllRequests(requests).build();

          System.out.println("Sending Batch Create Regions request");
          BatchCreateRegionsResponse response = regionsServiceClient.batchCreateRegions(request);
          System.out.println("Inserted Regions Names below");
          // The last part of the region name will be the ID of the region.
          // Format: `accounts/{account}/region/{region}`
          response.getRegionsList().forEach(region -> System.out.println(region.getName()));

        } catch (Exception e) {
          System.out.println(e);
        }
      }

      public static void main(String[] args) throws Exception {
        Config config = Config.load();
        // The unique IDs of the regions to create.
        List<String> regionIds = new ArrayList<>();
        regionIds.add("REGION_1");
        regionIds.add("REGION_2");
        regionIds.add("REGION_3");
        regionIds.add("REGION_4");
        regionIds.add("REGION_5");

        batchCreateRegions(config, regionIds);
      }
    }

## Update multiple regions

This example shows how to use `BatchUpdateRegions` to update the `displayName`
and `postalCodeArea` for two existing regions. You must supply a `region.name`
to update the targeted region.

> [!NOTE]
> **Note:** You can only update a region name by use of the Merchant Center user interface.

### Request

Construct the request URL as follows:

    POST https://merchantapi.googleapis.com/accounts/v1/accounts/{ACCOUNT_ID}/regions:batchUpdate

The request body contains a list of `requests`. Each object must specify the
`region` data to update. The `region.name` field must contain the ID of the
region to update, for example,"98005". Specify the resource as `name` rather
than `accounts/{ACCOUNT_ID}/regions/name`. Including `updateMask` to indicate
the fields to change is optional.

    {
      "requests": [
        {
          "region": {
            "name": "98005",
            "displayName": "Seattle Updated Region",
            "postalCodeArea": {
              "regionCode": "US",
              "postalCodes": [
                {
                  "begin": "98330"
                }
              ]
            }
          },
          "updateMask": "displayName,postalCodeArea"
        },
        {
          "region": {
            "name": "07086",
            "displayName": "NewYork Updated Region",
            "postalCodeArea": {
              "regionCode": "US",
              "postalCodes": [
                {
                  "begin": "11*"
                }
              ]
            }
          },
          "updateMask": "displayName,postalCodeArea"
        }
      ]
    }

### Response

A successful request returns a list of the updated `region` objects.

    {
      "regions": [
        {
          "name": "accounts/{ACCOUNT_ID}/regions/98005",
          "displayName": "Seattle Updated Region",
          "postalCodeArea": {
            "regionCode": "US",
            "postalCodes": [
              {
                "begin": "98330"
              }
            ]
          },
          "regionalInventoryEligible": true,
          "shippingEligible": true
        },
        {
          "name": "accounts/{ACCOUNT_ID}/regions/07086",
          "displayName": "NewYork Updated Region",
          "postalCodeArea": {
            "regionCode": "US",
            "postalCodes": [
              {
                "begin": "11*"
              }
            ]
          },
          "regionalInventoryEligible": true,
          "shippingEligible": true
        }
      ]
    }

The following sample demonstrates how to update multiple regions in a batch
request:

### Java

    import com.google.api.gax.core.FixedCredentialsProvider;
    import com.google.auth.oauth2.GoogleCredentials;
    import com.google.protobuf.FieldMask;
    import com.google.shopping.merchant.accounts.v1.BatchUpdateRegionsRequest;
    import com.google.shopping.merchant.accounts.v1.BatchUpdateRegionsResponse;
    import com.google.shopping.merchant.accounts.v1.Region;
    import com.google.shopping.merchant.accounts.v1.RegionsServiceClient;
    import com.google.shopping.merchant.accounts.v1.RegionsServiceSettings;
    import com.google.shopping.merchant.accounts.v1.UpdateRegionRequest;
    import java.util.ArrayList;
    import java.util.List;
    import shopping.merchant.samples.utils.Authenticator;
    import shopping.merchant.samples.utils.Config;

    /** This class demonstrates how to update multiple regions for a Merchant Center account. */
    public class BatchUpdateRegionsSample {

      private static String getParent(String accountId) {
        return String.format("accounts/%s", accountId);
      }

      private static String getRegionName(String accountId, String regionId) {
        return String.format("accounts/%s/regions/%s", accountId, regionId);
      }

      public static void batchUpdateRegions(Config config, List<String> regionIds) throws Exception {

        // Obtains OAuth token based on the user's configuration.
        GoogleCredentials credential = new Authenticator().authenticate();

        // Creates service settings using the credentials retrieved above.
        RegionsServiceSettings regionsServiceSettings =
            RegionsServiceSettings.newBuilder()
                .setCredentialsProvider(FixedCredentialsProvider.create(credential))
                .build();

        // Creates parent to identify where to update the regions.
        String parent = getParent(config.getAccountId().toString());
        String accountId = config.getAccountId().toString();

        // Calls the API and catches and prints any network failures/errors.
        try (RegionsServiceClient regionsServiceClient =
            RegionsServiceClient.create(regionsServiceSettings)) {

          List<UpdateRegionRequest> requests = new ArrayList<>();
          for (String regionId : regionIds) {
            requests.add(
                UpdateRegionRequest.newBuilder()
                    .setRegion(
                        Region.newBuilder()
                            .setName(getRegionName(accountId, regionId))
                            .setDisplayName("Updated Region " + regionId)
                            .build())
                    .setUpdateMask(FieldMask.newBuilder().addPaths("display_name").build())
                    .build());
          }

          BatchUpdateRegionsRequest request =
              BatchUpdateRegionsRequest.newBuilder().setParent(parent).addAllRequests(requests).build();

          System.out.println("Sending Batch Update Regions request");
          BatchUpdateRegionsResponse response = regionsServiceClient.batchUpdateRegions(request);
          System.out.println("Updated Regions Names below");
          // The last part of the region name will be the ID of the region.
          // Format: `accounts/{account}/region/{region}`
          response.getRegionsList().forEach(region -> System.out.println(region.getName()));

        } catch (Exception e) {
          System.out.println(e);
        }
      }

      public static void main(String[] args) throws Exception {
        Config config = Config.load();
        // The unique IDs of the regions to update.
        List<String> regionIds = new ArrayList<>();
        regionIds.add("REGION_1");
        regionIds.add("REGION_2");
        regionIds.add("REGION_3");
        regionIds.add("REGION_4");
        regionIds.add("REGION_5");

        batchUpdateRegions(config, regionIds);
      }
    }

## Delete multiple regions

You can delete multiple regions in a single call.

> [!NOTE]
> **Note:** The delete operation is idempotent. Attempting to delete a non-existent region does not cause an error.

### Request

This example shows how to use `BatchDeleteRegions` to delete two regions in a
single call.

    POST
    https://merchantapi.googleapis.com/accounts/v1/accounts/{ACCOUNT_ID}/regions:batchDelete

The request body contains a list of `requests`, where each object specifies the
`name` (without `"accounts/{ACCOUNT_ID}/regions/"`) of the region to delete.

    {
      "requests":
       [
        {
          "name": "98005"
        },
        {
          "name": "07086"
        }
       ]
    }

### Response

A successful request returns an empty response body, indicating that the
specified regions were deleted (or did not exist).

    {}

The following sample demonstrates how to delete multiple regions in a batch
request:

### Java

    import com.google.api.gax.core.FixedCredentialsProvider;
    import com.google.auth.oauth2.GoogleCredentials;
    import com.google.shopping.merchant.accounts.v1.BatchDeleteRegionsRequest;
    import com.google.shopping.merchant.accounts.v1.DeleteRegionRequest;
    import com.google.shopping.merchant.accounts.v1.RegionsServiceClient;
    import com.google.shopping.merchant.accounts.v1.RegionsServiceSettings;
    import java.util.ArrayList;
    import java.util.List;
    import shopping.merchant.samples.utils.Authenticator;
    import shopping.merchant.samples.utils.Config;

    /** This class demonstrates how to delete multiple regions for a Merchant Center account. */
    public class BatchDeleteRegionsSample {

      private static String getParent(String accountId) {
        return String.format("accounts/%s", accountId);
      }

      private static String getRegionName(String accountId, String regionId) {
        return String.format("accounts/%s/regions/%s", accountId, regionId);
      }

      public static void batchDeleteRegions(Config config, List<String> regionIds) throws Exception {

        // Obtains OAuth token based on the user's configuration.
        GoogleCredentials credential = new Authenticator().authenticate();

        // Creates service settings using the credentials retrieved above.
        RegionsServiceSettings regionsServiceSettings =
            RegionsServiceSettings.newBuilder()
                .setCredentialsProvider(FixedCredentialsProvider.create(credential))
                .build();

        // Creates parent to identify where to delete the regions.
        String parent = getParent(config.getAccountId().toString());
        String accountId = config.getAccountId().toString();

        // Calls the API and catches and prints any network failures/errors.
        try (RegionsServiceClient regionsServiceClient =
            RegionsServiceClient.create(regionsServiceSettings)) {

          List<DeleteRegionRequest> requests = new ArrayList<>();
          for (String regionId : regionIds) {
            requests.add(
                DeleteRegionRequest.newBuilder().setName(getRegionName(accountId, regionId)).build());
          }

          BatchDeleteRegionsRequest request =
              BatchDeleteRegionsRequest.newBuilder().setParent(parent).addAllRequests(requests).build();

          System.out.println("Sending Batch Delete Regions request");
          regionsServiceClient.batchDeleteRegions(request);
          System.out.println("Regions deleted successfully");

        } catch (Exception e) {
          System.out.println(e);
        }
      }

      public static void main(String[] args) throws Exception {
        Config config = Config.load();
        // The unique IDs of the regions to delete.
        List<String> regionIds = new ArrayList<>();
        regionIds.add("REGION_1");
        regionIds.add("REGION_2");
        regionIds.add("REGION_3");
        regionIds.add("REGION_4");
        regionIds.add("REGION_5");

        batchDeleteRegions(config, regionIds);
      }
    }

## Limitations

Before you begin, keep these rules in mind:

- **Atomic operations** : Batch requests are atomic. If any single operation within the batch fails (for example, one region fails to be created), the **entire batch will fail**, and no changes will be made. The API will return an error detailing the cause of the failure.
- **Batch limits** : Each batch request can contain a **maximum of 100** region operations.
- **Quotas** : These endpoints use the same quota groups as their single-operation counterparts (`regions.create`, `regions.delete`, `regions.update`).

## Common errors and issues

Here are a few common pitfalls and their solutions.

### "The number of requests in a batch is too large"

This error occurs if the number of operations in your requests array exceeds the
limit of 100.

    "error":
      {
        "code": 400,
        "message": "The number of requests in a batch is too large.",
        "status": "INVALID_ARGUMENT"
      }

To fix this, split your operations into multiple batch requests of 100 or fewer.

### Required field is missing

This error occurs when a required field is missing. The error message specifies
the missing parameter.

The error messages are as follows:

- For `batchCreate`: `[regionId] Required parameter: regionId`
- For `batchUpdate`: `[region.name] Required field not provided.`
- For `batchDelete`: `[name] Required parameter: name`

To fix this, verify all required fields are present in each operation. For
example, every entry in a `batchUpdate` request must include the `region.name`.
Posting the following request results in an error:

    {
      "requests":
      [
        {
          "region":
            {
              "displayName": "An update without a region name"
            },
            "updateMask": "displayName"
        }
      ]
    }

### "Region with specified ID already exists"

An error occurs if you try to create a region with a `regionId` that already
exists.

The error message is `[regionId] Region with specified id already exists.`.

To fix this, verify that all `regionId` values are unique within the batch and
don't conflict with existing regions.

### "Duplicate value found for field region.name or regionId found"

An error occurs if you try to create or update multiple regions with the same ID
within a single batch request.

The error message is `Duplicate value found for field {fieldName} in this batch
request with value {duplicated_value}.`.

To fix this, verify that all `regionId` (for `batchCreate`) or `region.name`
(for `batchUpdate`) values are unique within a single batch request.

### "Item not found"

When using `batchUpdate`, if any region specified in the request does not exist,
the entire batch will fail with a `404 NOT_FOUND` error. This is different from
`batchDelete`, which succeeds for nonexistent regions.

    "error": {
        "code": 404,
        "message": "item not found",
        "status": "NOT_FOUND"
    }

To fix this, verify that all regions you are attempting to update exist before
sending the request.