本指南介绍了可用于创建或修改精选包的方法。
创建甄选包
您可以使用 curators.curatedPackages.create 方法创建新的精选软件包。创建后,精选包处于 ACTIVE 状态,您在 CuratedPackage.accessSettings.allowlistedMediaPlanners 字段中指定的媒体策划人员可以订阅该精选包。媒体策划人员订阅后,可以识别实时出价中发送的、您的精选套装所定位的广告资源。
以下示例使用包含 CuratedPackage 对象的 JSON 正文发出 POST 请求,该请求会发送到 API 的端点。当您发送 curators.curatedPackages.create API 请求(如示例中所示)时,系统会为您指定的甄选合作伙伴账号创建甄选的软件包。
REST
请求
POST https://authorizedbuyersmarketplace.googleapis.com/v1beta/curators/[YOUR_ACCOUNT_ID]/curatedPackages?alt=json
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"displayName": "Premium Mobile Web Package",
"description": "High-performing mobile web inventory for premium brands.",
"floorPriceCpm": {
"currencyCode": "USD",
"units": "2",
"nanos": 500000000
},
"feeCpm": {
"currencyCode": "USD",
"units": "0",
"nanos": 150000000
},
"accessSettings": {
"allowlistedMediaPlanners": [
"mediaPlanners/987654321"
]
},
"targeting": {
"includedDeviceTypes": [
"DEVICE_TYPE_PHONE",
"DEVICE_TYPE_TABLET"
],
"includedEnvironment": "ENVIRONMENT_SITE"
}
}响应
{
"name": "curators/[YOUR_ACCOUNT_ID]/curatedPackages/123456789",
"displayName": "Premium Mobile Web Package",
"description": "High-performing mobile web inventory for premium brands.",
"createTime": "2026-06-01T16:00:00Z",
"updateTime": "2026-06-01T16:00:00Z",
"floorPriceCpm": {
"currencyCode": "USD",
"units": "2",
"nanos": 500000000
},
"feeCpm": {
"currencyCode": "USD",
"units": "0",
"nanos": 150000000
},
"state": "ACTIVE",
"accessSettings": {
"allowlistedMediaPlanners": [
"mediaPlanners/987654321"
]
},
"targeting": {
"includedDeviceTypes": [
"DEVICE_TYPE_PHONE",
"DEVICE_TYPE_TABLET"
],
"includedEnvironment": "ENVIRONMENT_SITE"
}
}Java
/* * Copyright (c) 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.api.services.samples.authorizedbuyers.marketplace.v1beta.curators.curatedPackages; import com.google.api.services.authorizedbuyersmarketplace.v1beta.AuthorizedBuyersMarketplace; import com.google.api.services.authorizedbuyersmarketplace.v1beta.model.AccessControlSettings; import com.google.api.services.authorizedbuyersmarketplace.v1beta.model.CuratedPackage; import com.google.api.services.authorizedbuyersmarketplace.v1beta.model.Money; import com.google.api.services.authorizedbuyersmarketplace.v1beta.model.PackageTargeting; import com.google.api.services.samples.authorizedbuyers.marketplace.v1beta.Utils; import java.io.IOException; import java.security.GeneralSecurityException; import java.util.List; import net.sourceforge.argparse4j.ArgumentParsers; import net.sourceforge.argparse4j.inf.ArgumentParser; import net.sourceforge.argparse4j.inf.ArgumentParserException; import net.sourceforge.argparse4j.inf.Namespace; public class CreateCuratedPackage { /** * Executes the create operation for a curated package. * * @param marketplaceClient the initialized Marketplace API client. * @param parent the parent resource name under which the curated package will be created. * @param newCuratedPackage the CuratedPackage object to create. * @throws IOException if the API returns an error. */ public static void execute( AuthorizedBuyersMarketplace marketplaceClient, String parent, CuratedPackage newCuratedPackage) throws IOException { System.out.printf("Creating Curated Package \"%s\" for curator with name \"%s\".%n", newCuratedPackage.getDisplayName(), parent); // Create a new curated package. CuratedPackage createdPackage = marketplaceClient .curators() .curatedPackages() .create(parent, newCuratedPackage) .execute(); System.out.println("Successfully created curated package:"); Utils.jsonPrettyPrint(createdPackage); } /** * Creates and configures the ArgumentParser for this sample. * * @return the configured ArgumentParser. */ private static ArgumentParser createArgumentParser() { ArgumentParser parser = ArgumentParsers.newFor("CreateCuratedPackage") .build() .defaultHelp(true) .description("Creates a new curated package for the given curator account."); // Required arguments. parser .addArgument("-a", "--account_id") .help("The account ID of the curator that will create the curated package.") .required(true) .type(Long.class); parser .addArgument("-d", "--display_name") .help("The display name of the curated package to be created.") .required(true); parser .addArgument("--allowed_media_planners") .help("The space-delimited resource names of media planners you want to grant access " + "to the curated package. Eligible media planners can be found use the " + "mediaPlanners.list method. To learn more, see: " + "https://developers.google.com/authorized-buyers/apis/marketplace/reference/rest/v1beta/mediaPlanners/list") .required(true) .nargs("+"); parser .addArgument("--included_data_segments") .help("The space-delimited resource names of the data segments you want to target. " + "You can find data segments for your account using the curators.dataSegments.list " + "method. To learn more, see:" + "https://developers.google.com/authorized-buyers/apis/marketplace/reference/rest/v1beta/curators.dataSegments/list") .required(true) .nargs("+"); parser .addArgument("-c", "--fee_currency_code") .help("The three-letter currency code defined in ISO 4217. For example, \"USD\".") .required(true); parser .addArgument("-u", "--fee_units") .help("The whole units of your CPM fee in the specified currency. For example, if " + "`currencyCode` were set to \"USD\", a value of \"1\" would be $1 USD for 1,000 " + "views.") .type(Long.class) .required(true); parser .addArgument("-n", "--fee_nanos") .help("The nano units of your CPM fee, representing a fraction of the specified " + "currency. For example, if `currencyCode` were set to \"USD\", a value of " + "\"20000000\" would be $0.02 USD for 1,000 views.") .type(Integer.class) .required(true); // Optional arguments. parser .addArgument("--description") .help("The description of the curated package."); return parser; } /** * Builds a CuratedPackage object from the parsed command-line arguments. * * @param parsedArgs the parsed command-line arguments. * @return the constructed CuratedPackage object. */ private static CuratedPackage buildCuratedPackage(Namespace parsedArgs) { String displayName = parsedArgs.getString("display_name"); String description = parsedArgs.getString("description"); List<String> allowedMediaPlanners = parsedArgs.getList("allowed_media_planners"); List<String> includedDataSegments = parsedArgs.getList("included_data_segments"); String feeCurrencyCode = parsedArgs.getString("fee_currency_code"); Long feeUnits = parsedArgs.getLong("fee_units"); Integer feeNanos = parsedArgs.getInt("fee_nanos"); CuratedPackage newCuratedPackage = new CuratedPackage() .setDisplayName(displayName) .setDescription(description); newCuratedPackage.setAccessSettings( new AccessControlSettings() .setAllowlistedMediaPlanners(allowedMediaPlanners)); PackageTargeting packageTargeting = new PackageTargeting() .setIncludedDataSegments(includedDataSegments); newCuratedPackage.setTargeting(packageTargeting); Money feeCpm = new Money() .setCurrencyCode(feeCurrencyCode) .setUnits(feeUnits) .setNanos(feeNanos); newCuratedPackage.setFeeCpm(feeCpm); return newCuratedPackage; } public static void main(String[] args) { ArgumentParser parser = createArgumentParser(); Namespace parsedArgs = null; try { parsedArgs = parser.parseArgs(args); } catch (ArgumentParserException ex) { parser.handleError(ex); System.exit(1); } AuthorizedBuyersMarketplace client = null; try { client = Utils.getMarketplaceClient(); } catch (IOException ex) { System.out.printf("Unable to create Marketplace API service:%n%s", ex); System.out.println("Did you specify a valid path to a service account key file?"); System.exit(1); } catch (GeneralSecurityException ex) { System.out.printf("Unable to establish secure HttpTransport:%n%s", ex); System.exit(1); } Long accountId = parsedArgs.getLong("account_id"); String parent = String.format("curators/%s", accountId); CuratedPackage newCuratedPackage = buildCuratedPackage(parsedArgs); try { execute(client, parent, newCuratedPackage); } catch (IOException ex) { System.out.printf("Marketplace API returned error response:%n%s", ex); System.exit(1); } } }
修改现有精选套餐
如需修改现有精选软件包,请使用 curators.curatedPackages.patch 方法。使用 patch 方法调整精选竞价包的显示名称、说明、最低价格、费用或定位条件。
以下示例使用包含 CuratedPackage 对象的 JSON 正文发出 PATCH 请求,该请求会发送到 API 的端点。
REST
请求
PATCH https://authorizedbuyersmarketplace.googleapis.com/v1beta/curators/[YOUR_ACCOUNT_ID]/curatedPackages/123456789?updateMask=displayName,description&alt=json
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json
{
"displayName": "Updated Premium Mobile Web Package",
"description": "An updated description for high-performing mobile web inventory."
}响应
{
"name": "curators/[YOUR_ACCOUNT_ID]/curatedPackages/123456789",
"displayName": "Updated Premium Mobile Web Package",
"description": "An updated description for high-performing mobile web inventory.",
"createTime": "2026-06-01T16:00:00Z",
"updateTime": "2026-06-01T16:10:00Z",
"floorPriceCpm": {
"currencyCode": "USD",
"units": "2",
"nanos": 500000000
},
"feeCpm": {
"currencyCode": "USD",
"units": "0",
"nanos": 150000000
},
"state": "ACTIVE",
"accessSettings": {
"allowlistedMediaPlanners": [
"mediaPlanners/987654321"
]
},
"targeting": {
"includedDeviceTypes": [
"DEVICE_TYPE_PHONE",
"DEVICE_TYPE_TABLET"
],
"includedEnvironment": "ENVIRONMENT_SITE"
}
}Java
/* * Copyright (c) 2026 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.api.services.samples.authorizedbuyers.marketplace.v1beta.curators.curatedPackages; import com.google.api.services.authorizedbuyersmarketplace.v1beta.AuthorizedBuyersMarketplace; import com.google.api.services.authorizedbuyersmarketplace.v1beta.model.CuratedPackage; import com.google.api.services.authorizedbuyersmarketplace.v1beta.model.Money; import com.google.api.services.authorizedbuyersmarketplace.v1beta.model.PackageTargeting; import com.google.api.services.samples.authorizedbuyers.marketplace.v1beta.Utils; import java.io.IOException; import java.security.GeneralSecurityException; import java.util.ArrayList; import java.util.List; import net.sourceforge.argparse4j.ArgumentParsers; import net.sourceforge.argparse4j.inf.ArgumentParser; import net.sourceforge.argparse4j.inf.ArgumentParserException; import net.sourceforge.argparse4j.inf.Namespace; public class PatchCuratedPackage { /** * Executes the patch operation for a curated package. * * @param marketplaceClient the initialized Marketplace API client. * @param name the full resource name of the curated package to patch. * @param patchedPackage the CuratedPackage object containing the fields to update. * @param updateMask the comma-separated string representing the fields to be updated. * @throws IOException if the API returns an error. */ public static void execute( AuthorizedBuyersMarketplace marketplaceClient, String name, CuratedPackage patchedPackage, String updateMask) throws IOException { CuratedPackage updatedPackage = marketplaceClient .curators() .curatedPackages() .patch(name, patchedPackage) .setUpdateMask(updateMask) .execute(); System.out.printf("Curated package updated: %s%n", name); Utils.jsonPrettyPrint(updatedPackage); } /** * Creates and configures the ArgumentParser for this sample. * * @return the configured ArgumentParser. */ private static ArgumentParser createArgumentParser() { ArgumentParser parser = ArgumentParsers.newFor("PatchCuratedPackage") .build() .defaultHelp(true) .description("Updates a specific curated package. To modify the state of a" + "curated package, use the curators.curatedPackages.activate or " + "curators.curatedPackages.deactivate methods instead."); // Required arguments. parser .addArgument("-a", "--account_id") .help("The account ID of the curator that created the curated package.") .required(true) .type(Long.class); parser .addArgument("-c", "--curated_package_id") .help("The resource ID of the curated package to update.") .required(true); // Optional arguments. parser .addArgument("-d", "--display_name") .help("The modified value of `CuratedPackage.displayName`."); parser .addArgument("--description") .help("The modified value of `CuratedPackage.description`."); parser .addArgument("--floor_currency_code") .help("The modified value of `CuratedPackage.floorPriceCpm.currencyCode`. This must " + "be a three-letter currency code defined in ISO 4217. For example, \"USD\"."); parser .addArgument("--floor_units") .help("The modified value of `CuratedPackage.floorPriceCpm.units`. This represents " + "whole units of the floor price in the specified currency. For example, if " + "`currencyCode` were set to \"USD\", a value of \"1\" would be $1 USD for 1,000 views.") .type(Long.class); parser .addArgument("--floor_nanos") .help("The modified value of `CuratedPackage.floorPriceCpm.nanos`. This represents " + "the nano units of the floor price in the specified currency. For example, if " + "`currencyCode` were set to \"USD\", a value of \"20000000\" would be $0.02 USD for " + "1,000 views.") .type(Integer.class); parser .addArgument("--included_data_segments") .help("A space-delimited list of modified values for " + "`CuratedPackage.targeting.includedDataSegments`. This replaces any previously " + "targeted data segments for the curated package. You must specify resource names of " + "the data segments you want to target. You can find data segments for your account " + "using the curators.dataSegments.list method. To learn more, see:" + "https://developers.google.com/authorized-buyers/apis/marketplace/reference/rest/v1beta/curators.dataSegments/list") .nargs("+"); parser .addArgument("--fee_currency_code") .help("The modified value of `CuratedPackage.feeCpm.currencyCode`. This must be a " + "three-letter currency code defined in ISO 4217. For example, \"USD\"."); parser .addArgument("--fee_units") .help("The modified value of `CuratedPackage.feeCpm.units.` This represents whole " + "units of your CPM fee in the specified currency. For example, if `currencyCode` " + "were set to \"USD\", a value of \"1\" would be $1 USD for 1,000 views.") .type(Long.class); parser .addArgument("--fee_nanos") .help("The modified value of `CuratedPackage.feeCpm.nanos`. The nano units of your " + "CPM fee, representing a fraction of the specified currency. For example, if " + "`currencyCode` were set to \"USD\", a value of \"20000000\" would be $0.02 USD for " + "1,000 views.") .type(Integer.class); return parser; } /** * Populates the CuratedPackage object with values provided via command-line arguments * and builds the update mask indicating which fields were set. * * @param parsedArgs the parsed command-line arguments. * @param patchedPackage the CuratedPackage object to populate. * @return a comma-separated string representing the update mask. */ private static String buildPatchedCuratedPackage( Namespace parsedArgs, CuratedPackage patchedPackage) { List<String> patchedFields = new ArrayList<>(); String displayName = parsedArgs.getString("display_name"); String description = parsedArgs.getString("description"); String floorCurrencyCode = parsedArgs.getString("floor_currency_code"); Long floorUnits = parsedArgs.getLong("floor_units"); Integer floorNanos = parsedArgs.getInt("floor_nanos"); List<String> includedDataSegments = parsedArgs.getList("included_data_segments"); String feeCurrencyCode = parsedArgs.getString("fee_currency_code"); Long feeUnits = parsedArgs.getLong("fee_units"); Integer feeNanos = parsedArgs.getInt("fee_nanos"); if (displayName != null) { patchedPackage.setDisplayName(displayName); patchedFields.add("displayName"); } if (description != null) { patchedPackage.setDescription(description); patchedFields.add("description"); } Money floorPriceCpm = new Money(); if (floorCurrencyCode != null) { floorPriceCpm.setCurrencyCode(floorCurrencyCode); patchedFields.add("floorPriceCpm.currencyCode"); } if (floorUnits != null) { floorPriceCpm.setUnits(floorUnits); patchedFields.add("floorPriceCpm.units"); } if (floorNanos != null) { floorPriceCpm.setNanos(floorNanos); patchedFields.add("floorPriceCpm.nanos"); } patchedPackage.setFloorPriceCpm(floorPriceCpm); if (includedDataSegments != null) { PackageTargeting packageTargeting = new PackageTargeting() .setIncludedDataSegments(includedDataSegments); patchedFields.add("targeting.includedDataSegments"); patchedPackage.setTargeting(packageTargeting); } Money feeCpm = new Money(); if (feeCurrencyCode != null) { feeCpm.setCurrencyCode(feeCurrencyCode); patchedFields.add("feeCpm.currencyCode"); } if (feeUnits != null) { feeCpm.setUnits(feeUnits); patchedFields.add("feeCpm.units"); } if (feeNanos != null) { feeCpm.setNanos(feeNanos); patchedFields.add("feeCpm.nanos"); } patchedPackage.setFeeCpm(feeCpm); return String.join(",", patchedFields); } public static void main(String[] args) { ArgumentParser parser = createArgumentParser(); Namespace parsedArgs = null; try { parsedArgs = parser.parseArgs(args); } catch (ArgumentParserException ex) { parser.handleError(ex); System.exit(1); } AuthorizedBuyersMarketplace client = null; try { client = Utils.getMarketplaceClient(); } catch (IOException ex) { System.out.printf("Unable to create Marketplace API service:%n%s", ex); System.out.println("Did you specify a valid path to a service account key file?"); System.exit(1); } catch (GeneralSecurityException ex) { System.out.printf("Unable to establish secure HttpTransport:%n%s", ex); System.exit(1); } Long accountId = parsedArgs.getLong("account_id"); String curatedPackageId = parsedArgs.getString("curated_package_id"); String name = String.format("curators/%s/curatedPackages/%s", accountId, curatedPackageId); CuratedPackage patchedCuratedPackage = new CuratedPackage(); String updateMask = buildPatchedCuratedPackage(parsedArgs, patchedCuratedPackage); if (updateMask.isEmpty()) { System.out.println("No fields were specified to patch. Exiting."); } else { try { execute(client, name, patchedCuratedPackage, updateMask); } catch (IOException ex) { System.out.printf("Marketplace API returned error response:%n%s", ex); System.exit(1); } } } }
当您发送 curators.curatedPackages.patch API 请求时,系统会根据您填充 updateMask 查询参数的方式以及在请求正文中发送的 CuratedPackage 对象来修改您指定的精选软件包。系统仅更新您通过 updateMask 查询参数指定的字段,并忽略请求正文中找到的任何其他字段。
后续步骤
如需详细了解您可以使用 curatedPackages 资源执行的其他工作流程,请查看以下内容:
- 了解如何使用 Marketplace API 激活和停用精选资源包。
- 了解如何使用 Marketplace API 查看精选资源包。