Thêm và quản lý sản phẩm

API phụ Products cho phép bạn quản lý toàn bộ vòng đời của sản phẩm trong Merchant Center. Bạn có thể sử dụng công cụ này để tải sản phẩm mới lên, cập nhật sản phẩm hiện có, truy xuất thông tin sản phẩm và xoá những sản phẩm bạn không còn bán nữa.

Các điểm cần cân nhắc đặc biệt

  • Bạn chỉ có thể chèn,cập nhật hoặc xoá sản phẩm nếu sản phẩm thuộc nguồn dữ liệu thuộc loại API. Bạn không thể chèn hoặc cập nhật sản phẩm trong nguồn dữ liệu sử dụng phương thức tải lên dựa trên tệp.
  • Để đảm bảo sản phẩm luôn phù hợp và không bị hết hạn , bạn nên cập nhật hoặc làm mới sản phẩm theo định kỳ (ít nhất là mỗi 30 ngày).

Điều kiện tiên quyết

Trước khi có thể thêm hoặc quản lý sản phẩm bằng API, bạn phải có ít nhất một nguồn dữ liệu được định cấu hình trong tài khoản Merchant Center.

Để tạo một nguồn dữ liệu, hãy sử dụng phương thức dataSources.create trong API phụ Nguồn dữ liệu. Để biết hướng dẫn chi tiết, hãy xem hướng dẫn Quản lý nguồn dữ liệu API để tải sản phẩm lên. Sau khi tạo một nguồn dữ liệu, hãy ghi lại name của nguồn dữ liệu đó (ví dụ: accounts/12345/dataSources/67890), vì bạn sẽ cần đến mã này cho các yêu cầu tạo, cập nhật hoặc xoá liên quan đến sản phẩm.

Thêm sản phẩm

Để thêm một sản phẩm mới vào tài khoản Merchant Center, bạn cần chèn một tài nguyên ProductInput vào một nguồn dữ liệu chính. Thao tác này sẽ tạo sản phẩm và bắt đầu xử lý. Các trường trong đối tượng productAttributes phải tuân thủ quy cách dữ liệu sản phẩm.

Sử dụng phương thức productInputs.insert và cung cấp name của nguồn dữ liệu chính làm tham số dataSource.

Ví dụ này chèn một sản phẩm mới cho cửa hàng trực tuyến vào một nguồn dữ liệu chính.

POST https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs:insert?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}
{
  "offerId": "SKU12345",
  "contentLanguage": "en",
  "feedLabel": "US",
  "productAttributes": {
    "title": "Classic Cotton T-Shirt",
    "description": "A comfortable, durable, and stylish t-shirt made from 100% cotton.",
    "link": "https://www.example.com/p/SKU12345",
    "imageLink": "https://www.example.com/img/SKU12345.jpg",
    "availability": "IN_STOCK",
    "price": {
      "amountMicros": "15990000", // 15.99 USD
      "currencyCode": "USD"
    },
    "condition": "NEW",
    "gtins": ["9780007350896", "93433295494587"]
  }
}

Một lệnh gọi thành công sẽ trả về tài nguyên ProductInput mới tạo. Trường name chứa giá trị nhận dạng duy nhất cho dữ liệu đầu vào của sản phẩm này, còn trường product chứa tên của sản phẩm đã xử lý cuối cùng mà sau này bạn có thể dùng để truy xuất.

{
 "name": "accounts/{ACCOUNT_ID}/productInputs/en~US~SKU12345",
 "product": "accounts/{ACCOUNT_ID}/products/en~US~SKU12345",
 "offerId": "SKU12345",
 "contentLanguage": "en",
 "feedLabel": "US",
 "productAttributes": {
   "title": "Classic Cotton T-Shirt",
   "description": "A comfortable, durable, and stylish t-shirt made from 100% cotton.",
   "link": "https://www.example.com/p/SKU12345",
   "imageLink": "https://www.example.com/img/SKU12345.jpg",
   "availability": "IN_STOCK",
   "price": {
     "amountMicros": "15990000",
     "currencyCode": "USD"
   },
   "condition": "NEW",
   "gtins": [
     "9780007350896"
   ]
 }
}

Các mã mẫu sau đây cho biết cách thêm một sản phẩm.

Java

import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.shopping.merchant.products.v1.Availability;
import com.google.shopping.merchant.products.v1.Condition;
import com.google.shopping.merchant.products.v1.InsertProductInputRequest;
import com.google.shopping.merchant.products.v1.ProductAttributes;
import com.google.shopping.merchant.products.v1.ProductInput;
import com.google.shopping.merchant.products.v1.ProductInputsServiceClient;
import com.google.shopping.merchant.products.v1.ProductInputsServiceSettings;
import com.google.shopping.merchant.products.v1.Shipping;
import com.google.shopping.type.Price;
import shopping.merchant.samples.utils.Authenticator;
import shopping.merchant.samples.utils.Config;

/** This class demonstrates how to insert a product input */
public class InsertProductInputSample {

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

  public static void insertProductInput(Config config, String dataSource) throws Exception {

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

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

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

    // Calls the API and catches and prints any network failures/errors.
    try (ProductInputsServiceClient productInputsServiceClient =
        ProductInputsServiceClient.create(productInputsServiceSettings)) {

      // Price to be used for shipping ($33.45).
      Price price = Price.newBuilder().setAmountMicros(33_450_000).setCurrencyCode("USD").build();

      Shipping shipping =
          Shipping.newBuilder()
              .setPrice(price)
              .setCountry("GB")
              .setService("1st class post")
              .build();

      Shipping shipping2 =
          Shipping.newBuilder()
              .setPrice(price)
              .setCountry("FR")
              .setService("1st class post")
              .build();

      ProductAttributes attributes =
          ProductAttributes.newBuilder()
              .setTitle("A Tale of Two Cities")
              .setDescription("A classic novel about the French Revolution")
              .setLink("https://exampleWebsite.com/tale-of-two-cities.html")
              .setImageLink("https://exampleWebsite.com/tale-of-two-cities.jpg")
              .setAvailability(Availability.IN_STOCK)
              .setCondition(Condition.NEW)
              .setGoogleProductCategory("Media > Books")
              .addGtins("9780007350896")
              .addShipping(shipping)
              .addShipping(shipping2)
              .build();

      // The datasource can be either a primary or supplemental datasource.
      InsertProductInputRequest request =
          InsertProductInputRequest.newBuilder()
              .setParent(parent)
              // You can only insert products into datasource types of Input "API" and "FILE", and
              // of Type "Primary" or "Supplemental."
              // This field takes the `name` field of the datasource.
              .setDataSource(dataSource)
              // If this product is already owned by another datasource, when re-inserting, the
              // new datasource will take ownership of the product.
              .setProductInput(
                  ProductInput.newBuilder()
                      .setContentLanguage("en")
                      .setFeedLabel("label")
                      .setOfferId("sku123")
                      .setProductAttributes(attributes)
                      .build())
              .build();

      System.out.println("Sending insert ProductInput request");
      ProductInput response = productInputsServiceClient.insertProductInput(request);
      System.out.println("Inserted ProductInput Name below");
      // The last part of the product name will be the product ID assigned to a product by Google.
      // Product ID has the format `contentLanguage~feedLabel~offerId`
      System.out.println(response.getName());
      System.out.println("Inserted Product Name below");
      System.out.println(response.getProduct());
    } catch (Exception e) {
      System.out.println(e);
    }
  }

  public static void main(String[] args) throws Exception {
    Config config = Config.load();
    // Identifies the data source that will own the product input.
    String dataSource = "accounts/" + config.getAccountId() + "/dataSources/{INSERT_DATASOURCE_ID}";

    insertProductInput(config, dataSource);
  }
}

PHP

use Google\ApiCore\ApiException;
use Google\Shopping\Merchant\Products\V1\Availability;
use Google\Shopping\Merchant\Products\V1\Condition;
use Google\Shopping\Merchant\Products\V1\ProductAttributes;
use Google\Shopping\Merchant\Products\V1\InsertProductInputRequest;
use Google\Shopping\Merchant\Products\V1\ProductInput;
use Google\Shopping\Merchant\Products\V1\Client\ProductInputsServiceClient;
use Google\Shopping\Merchant\Products\V1\Shipping;
use Google\Shopping\Type\Price;

/**
 * Uploads a product input to your Merchant Center account.
 */
class InsertProductInput
{

    // ENSURE you fill in the datasource ID for the sample to work.
    private const DATASOURCE = 'INSERT_DATASOURCE_ID';

    /**
     * A helper function to create the parent string.
     *
     * @param array $accountId
     *      The account that owns the product.
     *
     * @return string The parent has the format: `accounts/{account_id}`
     */
    private static function getParent($accountId)
    {
        return sprintf("accounts/%s", $accountId);
    }

    /**
     * Uploads a product input to your Merchant Center account. If an input
     * with the same feedLabel, contentLanguage, offerId, and dataSource
     * already exists, this method replaces that entry.
     *
     * After inserting, updating, or deleting a product input, it may take several
     * minutes before the processed product can be retrieved.
     *
     * @param array $config
     *      The configuration data used for authentication and getting the acccount
     *      ID.
     * @param string $dataSource
     *      The primary or supplemental product data source name. If the
     *      product already exists and data source provided is different, then the
     *      product will be moved to a new data source.
     *      Format: `accounts/{account}/dataSources/{datasource}`.
     *
     * @return void
     */
    public static function insertProductInputSample($config, $dataSource): void
    {

        // Gets the OAuth credentials to make the request.
        $credentials = Authentication::useServiceAccountOrTokenFile();

        // Creates options config containing credentials for the client to use.
        $options = ['credentials' => $credentials];

        // Creates a client.
        $productInputsServiceClient = new ProductInputsServiceClient($options);


        // Creates parent to identify where to insert the product.
        $parent = self::getParent($config['accountId']);

        // Calls the API and catches and prints any network failures/errors.
        try {

            // Price to be used for shipping ($33.45).
            $price = new Price(
                [
                    'amount_micros' => 33450000,
                    'currency_code' => 'USD'
                ]
            );

            $shipping = new Shipping(
                [
                    'price' => $price,
                    'country' => 'GB',
                    'service' => '1st class post'
                ]
            );

            $shipping2 = new Shipping(
                [
                    'price' => $price,
                    'country' => 'FR',
                    'service' => '1st class post'
                ]
            );

            // Creates the attributes of the product.
            $attributes = new ProductAttributes(
                [
                    'title' => 'A Tale of Two Cities',
                    'description' => 'A classic novel about the French Revolution',
                    'link' => 'https://exampleWebsite.com/tale-of-two-cities.html',
                    'image_link' =>
                        'https://exampleWebsite.com/tale-of-two-cities.jpg',
                    'availability' => Availability::IN_STOCK,
                    'condition' => Condition::PBNEW,
                    'google_product_category' => 'Media > Books',
                    'gtins' => ['9780007350896'],
                    'shipping' => [$shipping, $shipping2]
                ]
            );

            // Creates the productInput with the fundamental identifiers.
            $productInput = new ProductInput(
                [
                    'content_language' => 'en',
                    'feed_label' => 'label',
                    'offer_id' => 'sku123ABCD',
                    'product_attributes' => $attributes
                ]
            );

            // Prepares the request message.
            $request = new InsertProductInputRequest(
                [
                    'parent' => $parent,
                    'data_source' => $dataSource,
                    'product_input' => $productInput
                ]
            );

            print "Sending insert ProductInput request\n";
            $response = $productInputsServiceClient->insertProductInput($request);
            print "Inserted ProductInput Name below\n";
            print $response->getName() . "\n";
            print "Inserted Product Name below\n";
            print $response->getProduct() . "\n";
        } catch (ApiException $e) {
            print $e->getMessage();
        }
    }

    /**
     * Helper to execute the sample.
     *
     * @return void
     */
    public function callSample(): void
    {
        $config = Config::generateConfig();
        // Identifies the data source that will own the product input.
        $dataSource = sprintf(
            "accounts/%s/dataSources/%s",
            $config['accountId'],
            self::DATASOURCE
        );

        // Makes the call to insert a product to the MC account.
        self::insertProductInputSample($config, $dataSource);
    }
}


// Run the script
$sample = new InsertProductInput();
$sample->callSample();

Python

from examples.authentication import configuration
from examples.authentication import generate_user_credentials
from google.shopping import merchant_products_v1
from google.shopping.merchant_products_v1 import Availability
from google.shopping.merchant_products_v1 import Condition
from google.shopping.type import Price

_ACCOUNT = configuration.Configuration().read_merchant_info()
_PARENT = f"accounts/{_ACCOUNT}"

# You can only insert products into datasource types of Input "API" and
# "FILE", and of Type "Primary" or "Supplemental."
_DATA_SOURCE = "[INSERT_DATA_SOURCE_HERE]"
_DATA_SOURCE_NAME = f"accounts/{_ACCOUNT}/dataSources/{_DATA_SOURCE}"


def create_product_input():
  """Creates a `ProductInput` resource."""

  # Creates a shipping setting
  price = Price()
  price.amount_micros = 33_450_000
  price.currency_code = "GBP"

  shipping_option_1 = merchant_products_v1.Shipping()
  shipping_option_1.price = price
  shipping_option_1.country = "GB"
  shipping_option_1.service = "1st class post"

  price2 = Price()
  price2.amount_micros = 33_450_000
  price2.currency_code = "EUR"

  shipping_option_2 = merchant_products_v1.Shipping()
  shipping_option_2.price = price2
  shipping_option_2.country = "FR"
  shipping_option_2.service = "2nd class post"

  # Sets product attributes. Make sure to replace these values with your own.
  attributes = merchant_products_v1.ProductAttributes()
  attributes.title = "A Tale of Two Cities"
  attributes.description = "A classic novel about the French Revolution"
  attributes.link = "https://exampleWebsite.com/tale-of-two-cities.html"
  attributes.image_link = "https://exampleWebsite.com/tale-of-two-cities.jpg"
  attributes.price = price
  attributes.availability = Availability.IN_STOCK
  attributes.condition = Condition.NEW
  attributes.google_product_category = "Media > Books"
  attributes.gtins = ["9780007350896"]
  attributes.shipping = [shipping_option_1, shipping_option_2]

  return merchant_products_v1.ProductInput(
      content_language="en",
      feed_label="GB",
      offer_id="sku123",
      product_attributes=attributes,
  )


def insert_product_input():
  """Inserts the specified `ProductInput` resource."""

  # Gets OAuth Credentials.
  credentials = generate_user_credentials.main()

  # Creates a client.
  client = merchant_products_v1.ProductInputsServiceClient(
      credentials=credentials
  )

  # Creates the request.
  request = merchant_products_v1.InsertProductInputRequest(
      parent=_PARENT,
      # If this product is already owned by another datasource, when
      # re-inserting, the new datasource will take ownership of the product.
      product_input=create_product_input(),
      data_source=_DATA_SOURCE_NAME,
  )

  # Makes the request and catches and prints any error messages.
  try:
    response = client.insert_product_input(request=request)
    # The last part of the product name will be the product ID assigned to a
    # product by Google. Product ID has the format
    # `contentLanguage~feedLabel~offerId`
    print(f"Input successful: {response}")
  except RuntimeError as e:
    print("Input failed")
    print(e)
    # After the product is inserted, the product ID will be returned in the
    # response. We recommend that you check the Merchant Center to ensure that
    # the product is approved and visible to users before using the product ID
    # in any downstream processes.


if __name__ == "__main__":
  insert_product_input()

Apps_Script


/**
 * Inserts a product into the products list. Logs the API response.
 */
function productInsert() {
  // IMPORTANT:
  // Enable the Merchant API Products sub-API Advanced Service and call it
  // "MerchantApiProducts"

  // Replace this with your Merchant Center ID.
  const accountId = 'INSERT_MERCHANT_ID';

  // Replace this with the Data Source ID you want to use.
  const dataSourceId = 'INSERT_DATASOURCE_ID';

  // Construct the parent name
  const parent = 'accounts/' + accountId;

  // Construct the Data Source name
  const dataSource = parent + '/dataSources/' + dataSourceId;

  // Create a product resource and insert it
  const productResource = {
    'offerId': 'fromAppsScript',
    'contentLanguage': 'en',
    'feedLabel': 'US',
    'productAttributes': {
      'title': 'A Tale of Two Cities',
      'description': 'A classic novel about the French Revolution',
      'link': 'http://my-book-shop.com/tale-of-two-cities.html',
      'imageLink': 'http://my-book-shop.com/tale-of-two-cities.jpg',
      'availability': 'in stock',
      'condition': 'new',
      'googleProductCategory': 'Media > Books',
      'gtin': '[9780007350896]',
      'price': {'amountMicros': '2500000', 'currencyCode': 'USD'},
    }
  };

  try {
    console.log('Sending insert ProductInput request');
    // Call the ProductInputs.insert API method.
    response = MerchantApiProducts.Accounts.ProductInputs.insert(
        productResource, parent, {dataSource});
    // RESTful insert returns the JSON object as a response.
    console.log('Inserted ProductInput below');
    console.log(response);
  } catch (e) {
    console.log('ERROR!');
    console.log(e);
  }
}

cURL

curl -X POST \
"https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs:insert?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}" \
-H "Authorization: Bearer <API_TOKEN>" \
-H "Content-Type: application/json" \
-d '{
 "offerId": "SKU12345",
 "contentLanguage": "en",
 "feedLabel": "US",
 "productAttributes": {
   "title": "Classic Cotton T-Shirt",
   "description": "A comfortable, durable, and stylish t-shirt made from 100% cotton.",
   "link": "https://www.example.com/p/SKU12345",
   "imageLink": "https://www.example.com/img/SKU12345.jpg",
   "availability": "IN_STOCK",
   "price": {
     "amountMicros": "15990000",
     "currencyCode": "USD"
   },
   "condition": "NEW",
   "gtins": ["9780007350896"]
 }
}'

Thêm hoặc cập nhật thông tin sản phẩm bằng nguồn dữ liệu bổ sung

Sử dụng nguồn dữ liệu bổ sung để cung cấp dữ liệu bổ sung hoặc thay thế cho những sản phẩm đã có trong một nguồn dữ liệu chính. Điều này rất hữu ích khi bạn muốn thêm thông tin như chương trình khuyến mãi, nhãn tuỳ chỉnh hoặc ghi đè dữ liệu sản phẩm cụ thể mà không cần sửa đổi dữ liệu đầu vào ban đầu của sản phẩm.

Để thực hiện việc này, hãy sử dụng phương thức productInputs.insert, nhưng chỉ định name của nguồn dữ liệu bổ sung trong tham số dataSource. Xác minh rằng offerId, contentLanguagefeedLabel khớp với một sản phẩm hiện có.

Ví dụ này thêm một nhãn tuỳ chỉnh vào một sản phẩm hiện có bằng cách sử dụng một nguồn dữ liệu bổ sung.

POST https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs:insert?dataSource=accounts/{ACCOUNT_ID}/dataSources/{SUPPLEMENTAL_DATASOURCE_ID}
{
 "offerId": "SKU12345",
 "contentLanguage": "en",
 "feedLabel": "US",
 "productAttributes": {
   "customLabel0": "clearance-sale"
 }
}

Sau lệnh gọi này, Product cuối cùng sẽ có customLabel0 được đặt thành clearance-sale, giả sử nguồn dữ liệu bổ sung có mức độ ưu tiên cao hơn nguồn dữ liệu chính trong quy tắc nguồn cấp dữ liệu của bạn như được xác định bởi default_rule.

Thêm sản phẩm không đồng bộ

Để tải lên một số lượng lớn sản phẩm một cách hiệu quả, bạn có thể gửi đồng thời nhiều yêu cầu chèn. Thay vì chờ phản hồi cho từng yêu cầu trước khi gửi yêu cầu tiếp theo, bạn có thể gửi các yêu cầu này một cách không đồng bộ và xử lý các phản hồi khi chúng đến. Phương pháp này có thể cải thiện đáng kể tốc độ tải dữ liệu lên.

Các mẫu mã sau đây cho biết cách chèn sản phẩm không đồng bộ. Để tìm hiểu về cách thực hiện nhiều yêu cầu cùng một lúc bằng cách sử dụng curl, hãy xem phần Gửi nhiều yêu cầu cùng một lúc.

Java

import com.google.api.core.ApiFuture;
import com.google.api.core.ApiFutureCallback;
import com.google.api.core.ApiFutures;
import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.shopping.merchant.products.v1.Availability;
import com.google.shopping.merchant.products.v1.Condition;
import com.google.shopping.merchant.products.v1.InsertProductInputRequest;
import com.google.shopping.merchant.products.v1.ProductAttributes;
import com.google.shopping.merchant.products.v1.ProductInput;
import com.google.shopping.merchant.products.v1.ProductInputsServiceClient;
import com.google.shopping.merchant.products.v1.ProductInputsServiceSettings;
import com.google.shopping.merchant.products.v1.Shipping;
import com.google.shopping.type.Price;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import shopping.merchant.samples.utils.Authenticator;
import shopping.merchant.samples.utils.Config;

/** This class demonstrates how to insert a product input */
public class InsertProductInputAsyncSample {

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

  private static String generateRandomString() {
    String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    Random random = new Random();
    StringBuilder sb = new StringBuilder(8);
    for (int i = 0; i < 8; i++) {
      sb.append(characters.charAt(random.nextInt(characters.length())));
    }
    return sb.toString();
  }

  private static ProductInput createRandomProduct() {
    Price price = Price.newBuilder().setAmountMicros(33_450_000).setCurrencyCode("USD").build();

    Shipping shipping =
        Shipping.newBuilder().setPrice(price).setCountry("GB").setService("1st class post").build();

    Shipping shipping2 =
        Shipping.newBuilder().setPrice(price).setCountry("FR").setService("1st class post").build();

    ProductAttributes attributes =
        ProductAttributes.newBuilder()
            .setTitle("A Tale of Two Cities")
            .setDescription("A classic novel about the French Revolution")
            .setLink("https://exampleWebsite.com/tale-of-two-cities.html")
            .setImageLink("https://exampleWebsite.com/tale-of-two-cities.jpg")
            .setAvailability(Availability.IN_STOCK)
            .setCondition(Condition.NEW)
            .setGoogleProductCategory("Media > Books")
            .addGtins("9780007350896")
            .addShipping(shipping)
            .addShipping(shipping2)
            .build();

    return ProductInput.newBuilder()
        .setContentLanguage("en")
        .setFeedLabel("CH")
        .setOfferId(generateRandomString())
        .setProductAttributes(attributes)
        .build();
  }

  public static void asyncInsertProductInput(Config config, String dataSource) throws Exception {

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

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

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

    // Calls the API and catches and prints any network failures/errors.
    try (ProductInputsServiceClient productInputsServiceClient =
        ProductInputsServiceClient.create(productInputsServiceSettings)) {

      // Creates five insert product input requests with random product IDs.
      List<InsertProductInputRequest> requests = new ArrayList<>(5);
      for (int i = 0; i < 5; i++) {
        InsertProductInputRequest request =
            InsertProductInputRequest.newBuilder()
                .setParent(parent)
                // You can only insert products into datasource types of Input "API", and of Type
                // "Primary" or "Supplemental."
                // This field takes the `name` field of the datasource.
                .setDataSource(dataSource)
                // If this product is already owned by another datasource, when re-inserting, the
                // new datasource will take ownership of the product.
                .setProductInput(createRandomProduct())
                .build();

        requests.add(request);
      }

      System.out.println("Sending insert product input requests");
      List<ApiFuture<ProductInput>> futures =
          requests.stream()
              .map(
                  request ->
                      productInputsServiceClient.insertProductInputCallable().futureCall(request))
              .collect(Collectors.toList());

      // Creates callback to handle the responses when all are ready.
      ApiFuture<List<ProductInput>> responses = ApiFutures.allAsList(futures);
      ApiFutures.addCallback(
          responses,
          new ApiFutureCallback<List<ProductInput>>() {
            @Override
            public void onSuccess(List<ProductInput> results) {
              System.out.println("Inserted products below");
              System.out.println(results);
            }

            @Override
            public void onFailure(Throwable throwable) {
              System.out.println(throwable);
            }
          },
          MoreExecutors.directExecutor());

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

  public static void main(String[] args) throws Exception {
    Config config = Config.load();
    // Identifies the data source that will own the product input.
    String dataSource = "accounts/" + config.getAccountId() + "/dataSources/{datasourceId}";

    asyncInsertProductInput(config, dataSource);
  }
}

Python

import asyncio
import functools
import random
import string

from examples.authentication import configuration
from examples.authentication import generate_user_credentials
from google.shopping.merchant_products_v1 import Availability
from google.shopping.merchant_products_v1 import Condition
from google.shopping.merchant_products_v1 import InsertProductInputRequest
from google.shopping.merchant_products_v1 import ProductAttributes
from google.shopping.merchant_products_v1 import ProductInput
from google.shopping.merchant_products_v1 import ProductInputsServiceAsyncClient
from google.shopping.merchant_products_v1 import Shipping
from google.shopping.type import Price

# Read merchant account information from the configuration file.
_ACCOUNT_ID = configuration.Configuration().read_merchant_info()
# The parent account for the product input.
# Format: accounts/{account}
_PARENT = f"accounts/{_ACCOUNT_ID}"


def _generate_random_string(length: int = 8) -> str:
  """Generates a random string of a given length."""
  characters = string.ascii_letters + string.digits
  return "".join(random.choice(characters) for _ in range(length))


def _create_random_product() -> ProductInput:
  """Creates a ProductInput with random elements and predefined attributes."""
  price = Price(amount_micros=33450000, currency_code="USD")

  shipping1 = Shipping(price=price, country="GB", service="1st class post")
  shipping2 = Shipping(price=price, country="FR", service="1st class post")

  attributes = ProductAttributes(
      title="Async - A Tale of Two Cities",
      description="A classic novel about the French Revolution",
      link="https://exampleWebsite.com/tale-of-two-cities.html",
      image_link="https://exampleWebsite.com/tale-of-two-cities.jpg",
      availability=Availability.IN_STOCK,
      condition=Condition.NEW,
      google_product_category="Media > Books",
      gtins=["9780007350896"],
      shipping=[shipping1, shipping2],
  )

  return ProductInput(
      content_language="en",
      feed_label="US",
      offer_id=_generate_random_string(),
      product_attributes=attributes,
  )


def print_product_input(i, task):
  print("Inserted ProductInput number: ", i)
  # task.result() contains the response from async_insert_product_input
  print(task.result())


async def async_insert_product_input(
    client: ProductInputsServiceAsyncClient, request: InsertProductInputRequest
):
  """Inserts product inputs.

  Args:
    client: The ProductInputsServiceAsyncClient to use.
    request: The InsertProductInputRequest to send.

  Returns:
    The response from the insert_produc_input request.
  """

  print("Sending insert product input requests")

  try:
    response = await client.insert_product_input(request=request)
    # The response is an async corouting inserting the ProductInput.
    return response
  except RuntimeError as e:
    # Catch and print any exceptions that occur during the API calls.
    print(e)


async def main():
  # The ID of the data source that will own the product input.
  # This is a placeholder and should be replaced with an actual data source ID.
  datasource_id = "<INSERT_DATA_SOURCE_ID_HERE>"
  data_source_name = f"accounts/{_ACCOUNT_ID}/dataSources/{datasource_id}"

  # Gets OAuth Credentials.
  credentials = generate_user_credentials.main()

  # Creates a ProductInputsServiceClient.
  client = ProductInputsServiceAsyncClient(credentials=credentials)
  tasks = []
  for i in range(5):
    product_input = _create_random_product()
    request = InsertProductInputRequest(
        parent=_PARENT,
        data_source=data_source_name,
        product_input=product_input,
    )
    # Create the async task
    insert_product_task = asyncio.create_task(
        async_insert_product_input(client, request)
    )
    # Add the callback
    callback_function = functools.partial(print_product_input, i)
    insert_product_task.add_done_callback(callback_function)
    # Add the task to our list
    tasks.append(insert_product_task)

  # Await all tasks to complete concurrently
  # The print_product_input callback will be called for each as it finishes
  await asyncio.gather(*tasks)


if __name__ == "__main__":
  asyncio.run(main())

Thêm sản phẩm nhắm đến các quốc gia cụ thể

Bạn có thể đặt tiêu chí nhắm mục tiêu theo quốc gia cho từng sản phẩm để ghi đè các chế độ cài đặt trong nguồn dữ liệu hoặc để nhắm đến sản phẩm khi nguồn dữ liệu không xác định quốc gia.

Quốc gia mục tiêu có thuộc tính shipping

Nếu nguồn dữ liệu của bạn không xác định các quốc gia cụ thể, bạn có thể nhắm đến các quốc gia cho một sản phẩm bằng cách cung cấp trường shipping trong productAttributes. Trường này cho phép bạn chỉ định phí vận chuyển và quy tắc cho nhiều quốc gia, ngầm nhắm đến các quốc gia đó để phân phát.

Ví dụ này nhắm đến một sản phẩm ở Hoa Kỳ và Canada bằng cách cung cấp 2 mục shipping riêng biệt.

POST https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs:insert?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}
{
 "offerId": "SKU_SHIP_TARGET",
 "contentLanguage": "en",
 "feedLabel": "GLOBAL",
 "productAttributes": {
   "title": "Global T-Shirt",
   "link": "https://www.example.com/p/SKU_SHIP_TARGET",
   "imageLink": "https://www.example.com/img/SKU_SHIP_TARGET.jpg",
   "availability": "IN_STOCK",
   "price": {
     "amountMicros": "25990000",
     "currencyCode": "USD"
   },
   "shipping": [
     {
       "country": "US",
       "price": {
         "amountMicros": "5990000",
         "currencyCode": "USD"
       }
     },
     {
       "country": "CA",
       "price": {
         "amountMicros": "10990000",
         "currencyCode": "CAD"
       }
     }
   ]
 }
}

Loại trừ quốc gia và vị trí xuất hiện

Nếu nguồn dữ liệu của bạn đã nhắm đến nhiều quốc gia, bạn có thể loại trừ một sản phẩm khỏi việc xuất hiện ở một nhóm nhỏ các quốc gia đó hoặc khỏi các vị trí xuất hiện cụ thể.

  • Sử dụng thuộc tính shoppingAdsExcludedCountries để ngăn một sản phẩm xuất hiện trong quảng cáo Mua sắm ở một số quốc gia cụ thể.
  • Sử dụng thuộc tính excludedDestinations để ngăn một sản phẩm xuất hiện trong Phương thức tiếp thị cụ thể, chẳng hạn như FreeListings.

Ví dụ này giả định rằng nguồn dữ liệu nhắm đến Hoa Kỳ, Canada và Mexico. Yêu cầu này loại trừ sản phẩm khỏi quảng cáo Mua sắm ở Mexico và hoàn toàn khỏi vị trí xuất hiện Trang thông tin miễn phí.

POST https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs:insert?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}
{
  "offerId": "SKU_EXCLUDE_TARGET",
  "contentLanguage": "en",
  "feedLabel": "NA",
  "productAttributes": {
    "title": "North America T-Shirt",
    "link": "https://www.example.com/p/SKU_EXCLUDE_TARGET",
    "imageLink": "https://www.example.com/img/SKU_EXCLUDE_TARGET.jpg",
    "availability": "IN_STOCK",
    "price": {
      "amountMicros": "19990000",
      "currencyCode": "USD"
    },
    "shoppingAdsExcludedCountries": ["MX"],
    "excludedDestinations": ["FREE_LISTINGS"]
  }
}

Lấy thông tin sản phẩm

Để truy xuất trạng thái cuối cùng đã xử lý của một sản phẩm, hãy sử dụng phương thức products.get. Phương thức này trả về tài nguyên Product, bao gồm tất cả productAttributes sau khi áp dụng quy tắc nguồn cấp dữ liệu và nguồn dữ liệu bổ sung, cùng với trạng thái xác thực hiện tại.

Có thể mất vài phút kể từ khi bạn chèn hoặc cập nhật một ProductInput cho đến khi Product cuối cùng có thể truy xuất được.

GET https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/products/en~US~SKU12345

Một yêu cầu thành công sẽ trả về tài nguyên Product.

{
 "name": "accounts/{ACCOUNT_ID}/products/en~US~SKU12345",
 "offerId": "SKU12345",
 "contentLanguage": "en",
 "feedLabel": "US",
 "dataSource": "accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}",
 "productAttributes": {
   "title": "Classic Cotton T-Shirt",
   "description": "A comfortable, durable, and stylish t-shirt made from 100% cotton.",
   "link": "https://www.example.com/p/SKU12345",
   "imageLink": "https://www.example.com/img/SKU12345.jpg",
   "availability": "IN_STOCK",
   "price": {
     "amountMicros": "15990000",
     "currencyCode": "USD"
   },
   "condition": "NEW",
   "gtins": [
     "9780007350896"
   ]
 },
 "productStatus": {
   "destinationStatuses": [
     {
       "reportingContext": "SHOPPING_ADS",
       "approvedCountries": [
         "US"
       ]
     }
   ],
   "creationDate": "2024-05-20T10:00:00Z",
   "lastUpdateDate": "2024-05-20T10:05:00Z",
   "googleExpirationDate": "2024-06-19T10:05:00Z"
 }
}

Các mã mẫu sau đây cho biết cách lấy một sản phẩm.

Java

import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.shopping.merchant.products.v1.GetProductRequest;
import com.google.shopping.merchant.products.v1.Product;
import com.google.shopping.merchant.products.v1.ProductsServiceClient;
import com.google.shopping.merchant.products.v1.ProductsServiceSettings;
import shopping.merchant.samples.utils.Authenticator;
import shopping.merchant.samples.utils.Config;

/** This class demonstrates how to get a single product for a given Merchant Center account */
public class GetProductSample {

  public static void getProduct(Config config, String product) throws Exception {

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

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

    // Calls the API and catches and prints any network failures/errors.
    try (ProductsServiceClient productsServiceClient =
        ProductsServiceClient.create(productsServiceSettings)) {

      // The name has the format: accounts/{account}/products/{productId}
      GetProductRequest request = GetProductRequest.newBuilder().setName(product).build();

      System.out.println("Sending get product request:");
      Product response = productsServiceClient.getProduct(request);

      System.out.println("Retrieved Product below");
      System.out.println(response);
    } catch (Exception e) {
      System.out.println(e);
    }
  }

  public static void main(String[] args) throws Exception {
    Config config = Config.load();
    // The name of the `product`, returned after a `Product.insert` request. We recommend
    // having stored this value in your database to use for all future requests.
    String product = "accounts/{datasource}/products/{productId}";

    getProduct(config, product);
  }
}

PHP

use Google\ApiCore\ApiException;
use Google\Shopping\Merchant\Products\V1\GetProductRequest;
use Google\Shopping\Merchant\Products\V1\Product;
use Google\Shopping\Merchant\Products\V1\Client\ProductsServiceClient;


/**
 * This class demonstrates how to get a single product for a given Merchant Center
 * account.
 */
class GetProduct
{

    // ENSURE you fill in the product ID for the sample to work.
    private const PRODUCT = 'INSERT_PRODUCT_ID_HERE';

    /**
     * Gets a product from your Merchant Center account.
     *
     * @param array  $config
     *      The configuration data used for authentication and getting the acccount
     *      ID.
     * @param string $product
     *      The product ID to get.
     *      Format: `accounts/{account}/products/{productId}`.
     *
     * @return void
     */
    public static function getProductSample($config, $product) : void
    {
        // Gets the OAuth credentials to make the request.
        $credentials = Authentication::useServiceAccountOrTokenFile();

        // Creates options config containing credentials for the client to use.
        $options = ['credentials' => $credentials];

        // Creates a client.
        $productsServiceClient = new ProductsServiceClient($options);

        try {
            // Creates the request.
            $request = new GetProductRequest(
                [
                    'name' => $product
                ]
            );

            // Sends the request.
            echo "Sending get Product request\n";
            $response = $productsServiceClient->getProduct($request);

            // Outputs the response.
            echo "Retrieved Product below\n";
            print_r($response);
        } catch (Exception $e) {
            echo $e->getMessage();
        }
    }

    /**
     * Helper to execute the sample.
     *
     * @return void
     */
    public function callSample(): void
    {
        $config = Config::generateConfig();
        // Identifies the product to retrieve.
        // The name has the format: accounts/{account}/products/{productId}.
        $product = ProductsServiceClient::productName(
            $config['accountId'],
            self::PRODUCT
        );

        self::getProductSample($config, $product);
    }

}


$sample = new GetProduct();
$sample->callSample();

Python

from examples.authentication import configuration
from examples.authentication import generate_user_credentials
from google.shopping import merchant_products_v1


_ACCOUNT = configuration.Configuration().read_merchant_info()

# ENSURE you fill in the product ID for the sample to
# work.
# In the format of `contentLanguage~feedLabel~offerId`
_PRODUCT = "[INSERT_PRODUCT_HERE]"
_NAME = f"accounts/{_ACCOUNT}/products/{_PRODUCT}"


def get_product():
  """Gets the specified `Product` resource."""

  # Gets OAuth Credentials.
  credentials = generate_user_credentials.main()

  # Creates a client.
  client = merchant_products_v1.ProductsServiceClient(
      credentials=credentials
  )

  # Creates the request.
  request = merchant_products_v1.GetProductRequest(name=_NAME)

  # Makes the request and catches and prints any error messages.
  try:
    response = client.get_product(request=request)
    print(f"Get successful: {response}")
  except RuntimeError as e:
    print("Get failed")
    print(e)


if __name__ == "__main__":
  get_product()

Apps_Script

/**
 * Get a specific product for a given Merchant Center account.
 */
function getProduct() {
  // IMPORTANT:
  // Enable the Merchant API Products sub-API Advanced Service and call it
  // "MerchantApiProducts"

  // Replace this with your Merchant Center ID.
  const accountId = '<MERCHANT_CENTER_ID>';

  // The ID of the product to retrieve.
  // This ID is assigned by Google and typically follows the format:
  // channel~contentLanguage~feedLabel~offerId
  // Replace with an actual product ID from your Merchant Center account.
  const productId = '<PRODUCT_ID>';

  // Construct the parent name
  const parent = 'accounts/' + accountId;

  // Construct the product resource name
  const name = parent + "/products/" + productId;

  try {
    console.log('Sending get Product request');
    // Call the Products.get API method.
    product = MerchantApiProducts.Accounts.Products.get(name);
    console.log(product);
  } catch (e) {
    console.log('ERROR!');
    console.log(e);
  }
}

cURL

curl -X GET \
"https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/products/en~US~SKU12345" \
-H "Authorization: Bearer <API_TOKEN>"

Xoá một sản phẩm khỏi nguồn dữ liệu

Để xoá một dữ liệu đầu vào sản phẩm khỏi một nguồn dữ liệu cụ thể, hãy sử dụng phương thức productInputs.delete.

  • Nếu bạn xoá khỏi nguồn dữ liệu chính, toàn bộ sản phẩm (bao gồm cả ProductInputs bổ sung) sẽ bị xoá khỏi Merchant Center.
  • Nếu bạn xoá khỏi nguồn dữ liệu bổ sung, thì chỉ các thuộc tính trong nguồn dữ liệu đó bị xoá khỏi sản phẩm. Bản thân sản phẩm vẫn còn, được lấy từ nguồn dữ liệu chính và mọi nguồn dữ liệu bổ sung khác.

Bạn phải chỉ định dataSource mà bạn đang xoá dữ liệu đầu vào của sản phẩm.

DELETE https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs/en~US~SKU12345?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}

Một lệnh gọi thành công sẽ trả về một phản hồi trống.

Các mẫu mã sau đây cho biết cách xoá một sản phẩm.

Java

import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.shopping.merchant.products.v1.DeleteProductInputRequest;
import com.google.shopping.merchant.products.v1.ProductInputName;
import com.google.shopping.merchant.products.v1.ProductInputsServiceClient;
import com.google.shopping.merchant.products.v1.ProductInputsServiceSettings;
import shopping.merchant.samples.utils.Authenticator;
import shopping.merchant.samples.utils.Config;

/** This class demonstrates how to delete a product for a given Merchant Center account */
public class DeleteProductInputSample {

  public static void deleteProductInput(Config config, String productId, String dataSource)
      throws Exception {

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

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

    // Creates product name to identify product.
    String name =
        ProductInputName.newBuilder()
            .setAccount(config.getAccountId().toString())
            .setProductinput(productId)
            .build()
            .toString();

    // Calls the API and catches and prints any network failures/errors.
    try (ProductInputsServiceClient productInputsServiceClient =
        ProductInputsServiceClient.create(productInputsServiceSettings)) {
      DeleteProductInputRequest request =
          DeleteProductInputRequest.newBuilder().setName(name).setDataSource(dataSource).build();

      System.out.println("Sending deleteProductInput request");
      productInputsServiceClient.deleteProductInput(request); // no response returned on success
      System.out.println(
          "Delete successful, note that it may take a few minutes for the delete to update in"
              + " the system. If you make a products.get or products.list request before a few"
              + " minutes have passed, the old product data may be returned.");
    } catch (Exception e) {
      System.out.println(e);
    }
  }

  public static void main(String[] args) throws Exception {
    Config config = Config.load();
    // An ID assigned to a product by Google. In the format
    // contentLanguage~feedLabel~offerId
    String productId = "online~en~label~sku123";

    // The name of the dataSource from which to delete the product. If it is a primary feed, this
    // will delete the product completely. If it's a supplemental feed, it will only delete the
    // product information from that feed, but the product will still be available from the primary
    // feed.
    String dataSource = "accounts/{account}/dataSources/{dataSource}";

    deleteProductInput(config, productId, dataSource);
  }
}

PHP

use Google\ApiCore\ApiException;
use Google\Auth\CredentialsLoader;
use Google\Shopping\Merchant\Products\V1\Client\ProductInputsServiceClient;
use Google\Shopping\Merchant\Products\V1\DeleteProductInputRequest;
use Google\Shopping\Merchant\Products\V1\ProductInputName;

/**
 * This class demonstrates how to delete a productinput for a given Merchant Center
 * account.
 */

class DeleteProductInput
{

    // ENSURE you fill in the product and datasource ID for the sample to work.
    // An ID assigned to a product by Google:
    // In the format `contentLanguage~feedLabel~offerId`
    private const PRODUCT = 'INSERT_PRODUCT_ID_HERE';
    private const DATASOURCE = 'INSERT_DATASOURCE_ID_HERE';

    /**
     * Deletes a product input to your Merchant Center account.
     *
     * @param array  $config
     *      The configuration data used for authentication and getting the
     *      acccount ID.
     * @param string $product
     *      The product ID to delete.
     *      Format: `accounts/{account}/products/{productId}`.
     * @param string $dataSource
     *      The primary or supplemental product data source name that owns the
     *      product.
     *      Format: `accounts/{account}/dataSources/{datasource}`.
     *
     * @return void
     */
    public static function deleteProductInputSample(
        $config, $product, $dataSource
    ): void {
        // Obtains OAuth token based on the user's configuration.
        $credentials = Authentication::useServiceAccountOrTokenFile();

        // Creates service settings using the credentials retrieved above.
        $options = ['credentials' => $credentials];

        $productInputsServiceClient = new ProductInputsServiceClient($options);

        // Calls the API and catches and prints any network failures/errors.
        try {

            $request = new DeleteProductInputRequest(
                [
                    'name' => $product,
                    'data_source' => $dataSource
                ]
            );

            echo "Sending deleteProductInput request\n";
            $productInputsServiceClient->deleteProductInput($request);
            echo "Delete successful, note that it may take a few minutes for the "
            . "delete to update in the system. If you make a products.get or "
            . "products.list request before a few  minutes have passed, the old "
            . "product data may be returned.\n";
        } catch (ApiException $e) {
            echo "An error has occurred: \n";
            echo $e->getMessage() . "\n";
        }
    }

    /**
     * Helper to execute the sample.
     *
     * @return void
     */
    public function callSample(): void
    {
        $config = Config::generateConfig();

        // The productID variable is defined at the top of the file.
        $product = ProductInputsServiceClient::productInputName(
            $config['accountId'],
            self::PRODUCT
        );

        // The name of the dataSource from which to delete the product.
        $dataSource = sprintf(
            'accounts/%s/dataSources/%s',
            $config['accountId'],
            self::DATASOURCE
        );
        self::deleteProductInputSample($config, $product, $dataSource);
    }
}


// Run the script.
$sample = new DeleteProductInput();
$sample->callSample();

Python

from examples.authentication import configuration
from examples.authentication import generate_user_credentials
from google.shopping import merchant_products_v1


_ACCOUNT = configuration.Configuration().read_merchant_info()

# ENSURE you fill in the product ID and data source for the
# sample to work.
# In the format of `contentLanguage~feedLabel~offerId`
_PRODUCT = "[INSERT_PRODUCT_HERE]"
_DATA_SOURCE = "[INSERT_DATA_SOURCE_HERE]"
_NAME = f"accounts/{_ACCOUNT}/productInputs/{_PRODUCT}"
_DATA_SOURCE_NAME = f"accounts/{_ACCOUNT}/dataSources/{_DATA_SOURCE}"


def delete_product_input():
  """Deletes the specified `ProductInput` resource."""

  # Gets OAuth Credentials.
  credentials = generate_user_credentials.main()

  # Creates a client.
  client = merchant_products_v1.ProductInputsServiceClient(
      credentials=credentials
  )

  # Creates the request.
  request = merchant_products_v1.DeleteProductInputRequest(
      name=_NAME, data_source=_DATA_SOURCE_NAME
  )

  # Makes the request and catch and print any error messages.
  try:
    client.delete_product_input(request=request)
    print("Deletion successful")
  except RuntimeError as e:
    print("Deletion failed")
    print(e)


if __name__ == "__main__":
  delete_product_input()

cURL

curl -X DELETE \
"https://merchantapi.googleapis.com/products/v1/accounts/{ACCOUNT_ID}/productInputs/en~US~SKU12345?dataSource=accounts/{ACCOUNT_ID}/dataSources/{DATASOURCE_ID}" \
-H "Authorization: Bearer <API_TOKEN>"