選項說明

簡介

零接觸註冊 API 可協助裝置經銷商自動整合。貴組織的銷售工具可內建零接觸註冊功能,讓使用者和客戶更有效率。使用 API 協助使用者:

  • 將購買的裝置指派給客戶的零接觸註冊機制帳戶。
  • 建立客戶的零接觸註冊機制帳戶。
  • 將貴機構的電話和訂單中繼資料附加到裝置。
  • 建立有關指派給客戶的裝置報表。

本文件將介紹 API 並說明這些模式。如果您想自行探索 API,請試試 Java.NETPython 的快速入門指南。

API 概念

客戶和裝置是您在 API 中使用的核心資源。如要建立 請撥打 create。您可以使用聲明 API 方法建立裝置 (請參閱下文)。貴機構也可以使用零接觸註冊機制入口網站建立客戶和裝置。

裝置和客戶資源的關係

客戶
貴機構銷售裝置的公司。客戶擁有name 以及 ID。如果客戶想認領或尋找裝置,請直接採用客戶。目的地: 詳情請參閱 Customer
裝置
為貴機構支援零接觸註冊機制的 Android 或 ChromeOS 裝置 銷售給客戶裝置具有硬體 ID、中繼資料和客戶宣稱。裝置是 API 的核心,因此您幾乎會在所有方法中使用裝置。詳情請參閱 Device
裝置識別碼
封裝 IMEI 或 MEID 等硬體 ID,用於識別製造裝置。使用 DeviceIdentifier 指定要尋找、更新或聲明擁有權的裝置。詳情請參閱: ID
DeviceMetadata
儲存裝置的中繼資料鍵/值組合。使用 DeviceMetadata 儲存貴機構的中繼資料。目的地: 詳情請參閱「裝置中繼資料」。

如要列出應用程式可使用的所有 API 方法和資源,請參閱 API 參考資料

建立客戶

如果是 Android 裝置,經銷商會負責建立客戶 帳戶。客戶會使用這個帳戶存取零接觸入口網站,為裝置設定佈建設定。如果 ChromeOS 裝置已安裝 Google 要用來調整佈建設定的 Workspace 帳戶。

您可以呼叫 create API 方法來建立 的客戶帳戶採用零接觸註冊機制由於客戶會在零接觸註冊入口網站中看到公司名稱,因此應用程式的使用者應確認公司名稱是否正確。建立客戶名稱後,即無法編輯 用來追蹤協助客戶的客服專員姓名

您必須提供至少一個與 Google 帳戶相關聯的企業電子郵件地址,才能成為擁有者。無法將個人 Gmail 帳戶用於 也能使用 Google Cloud CLI 或 Compute Engine API如果客戶需要協助連結帳戶,請傳送 相關指示 與 Google 帳戶建立關聯

透過呼叫 API 建立客戶後,他們會管理員工的 入口網站存取權 - 無法編輯客戶的以及如何使用 API程式碼片段 以下說明如何建立客戶:

Java

// Provide the customer data as a Company type.
// The API requires a name and owners.
Company customer = new Company();
customer.setCompanyName("XYZ Corp");
customer.setOwnerEmails(Arrays.asList("liz@example.com", "darcy@example.com"));
customer.setAdminEmails(Collections.singletonList("jane@example.com"));

// Use our reseller ID for the parent resource name.
String parentResource = String.format("partners/%d", PARTNER_ID);

// Call the API to create the customer using the values in the company object.
CreateCustomerRequest body = new CreateCustomerRequest();
body.setCustomer(customer);
Company response = service.partners().customers().create(parentResource, body).execute();

.NET

// Provide the customer data as a Company type.
// The API requires a name and owners.
var customer = new Company
{
    CompanyName = "XYZ Corp",
    OwnerEmails = new String[] { "liz@example.com", "darcy@example.com" },
    AdminEmails = new String[] { "jane@example.com" }
};

// Use our reseller ID for the parent resource name.
var parentResource = String.Format("partners/{0}", PartnerId);

// Call the API to create the customer using the values in the company object.
var body = new CreateCustomerRequest
{
    Customer = customer
};
var request = service.Partners.Customers.Create(body, parentResource);
var response = request.Execute();

Python

# Provide the customer data as a Company type. The API requires
# a name and at least one owner.
company = {'companyName':'XYZ Corp', \
  'ownerEmails':['liz@example.com', 'darcy@example.com'], \
  'adminEmails':['jane@example.com']}

# Use our reseller ID for the parent resource name.
parent_resource = 'partners/{0}'.format(PARTNER_ID)

# Call the API to create the customer using the values in the company object.
response = service.partners().customers().create(parent=parent_resource,
    body={'customer':company}).execute()

如要進一步瞭解客戶員工的擁有者和管理員角色, 請參閱「入口網站使用者」一文。

為客戶認領裝置

客戶購買裝置後,會想在帳戶中設定這些裝置的佈建設定。聲明裝置擁有權後,會新增這部裝置 導入零接觸註冊機制,讓客戶能夠 帳戶管理設定。

裝置的佈建記錄包含零接觸註冊機制專用區段。個人中心 以指派裝置的方式, 用來追蹤協助客戶的客服專員姓名呼叫 partners.devices.claimpartners.devices.claimAsync 方法,並將客戶做為引數。一律提供 SECTION_TYPE_ZERO_TOUCH 做為 sectionType

您必須先取消聲明客戶的裝置 (請參閱下方說明),才能為其他客戶聲明相同裝置。建立新裝置時,聲明方法會驗證 DeviceIdentifier 欄位,包括 IMEI 或 MEID、序號、製造商名稱和型號,以及 ChromeOS 裝置的認證裝置 ID。

以下程式碼片段說明如何聲明裝置:

Java

// Identify the device to claim.
DeviceIdentifier identifier = new DeviceIdentifier();
// The manufacturer value is optional but recommended for cellular devices
identifier.setManufacturer("Google");
identifier.setImei("098765432109875");

// Create the body to connect the customer with the device.
ClaimDeviceRequest body = new ClaimDeviceRequest();
body.setDeviceIdentifier(identifier);
body.setCustomerId(customerId);
body.setSectionType("SECTION_TYPE_ZERO_TOUCH");

// Claim the device.
ClaimDeviceResponse response = service.partners().devices().claim(PARTNER_ID, body).execute();

.NET

// Identify the device to claim.
var deviceIdentifier = new DeviceIdentifier
{
    // The manufacturer value is optional but recommended for cellular devices
    Manufacturer = "Google",
    Imei = "098765432109875"
};

// Create the body to connect the customer with the device.
ClaimDeviceRequest body = new ClaimDeviceRequest
{
    DeviceIdentifier = deviceIdentifier,
    CustomerId = CustomerId,
    SectionType = "SECTION_TYPE_ZERO_TOUCH"
};

// Claim the device.
var response = service.Partners.Devices.Claim(body, PartnerId).Execute();

Python

# Identify the device to claim.
# The manufacturer value is optional but recommended for cellular devices
device_identifier = {'manufacturer':'Google', 'imei':'098765432109875'}

# Create the body to connect the customer with the device.
request_body = {'deviceIdentifier':device_identifier, \
    'customerId':customer_id, \
    'sectionType':'SECTION_TYPE_ZERO_TOUCH'}

# Claim the device.
response = service.partners().devices().claim(partnerId=PARTNER_ID,
    body=request_body).execute()

取消聲明裝置

貴機構可以取消聲明擁有客戶的裝置。取消聲明裝置會將其從零接觸註冊機制中移除。經銷商可能會取消認領以下裝置: 他們想要遷移至其他帳戶、退回或收到了錯誤的聲明。 呼叫 partners.devices.unclaim 方法或 :partners.devices.unclaimAsync:撤銷 客戶的裝置。

供應商

您可以使用供應商來代表經銷商合作夥伴、全球經銷商網路中的當地作業人員,或是任何代表您銷售裝置的機構。供應商可協助您區分使用者、客戶和裝置:

  • 您建立的供應商無法查看您的零接觸註冊機制帳戶或其他帳戶。
  • 您可以查看供應商的客戶和裝置,也可以取消註冊 供應商的裝置。不過,您無法將裝置指派給供應商 以更全面、準確的方式回答顧客問題 並與顧客自然流暢地對話

使用入口網站為貴機構建立供應商,您無法使用 API。您的帳戶角色必須是擁有者,才能建立新的供應商。如果貴機構有供應商 您可以呼叫 partners.vendors.list 列出 供應商和 partners.vendors.customers.list 吸引供應商的客戶以下範例會同時使用這兩種方法,列印顯示供應商客戶服務條款狀態的報表:

Java

// First, get the organization's vendors.
String parentResource = String.format("partners/%d", PARTNER_ID);
ListVendorsResponse results = service.partners().vendors().list(parentResource).execute();
if (results.getVendors() == null) {
  return;
}

// For each vendor, report the company name and a maximum 5 customers.
for (Company vendor: results.getVendors()) {
  System.out.format("\n%s customers\n", vendor.getCompanyName());
  System.out.println("---");
  // Use the vendor's API resource name as the parent resource.
  AndroidProvisioningPartner.Partners.Vendors.Customers.List customerRequest =
      service.partners().vendors().customers().list(vendor.getName());
  customerRequest.setPageSize(5);
  ListVendorCustomersResponse customerResponse = customerRequest.execute();

  List<Company> customers = customerResponse.getCustomers();
  if (customers == null) {
    System.out.println("No customers");
    break;
  } else {
    for (Company customer: customers) {
      System.out.format("%s: %s\n",
          customer.getCompanyName(),
          customer.getTermsStatus());
    }
  }
}

.NET

// First, get the organization's vendors.
var parentResource = String.Format("partners/{0}", PartnerId);
var results = service.Partners.Vendors.List(parentResource).Execute();
if (results.Vendors == null)
{
    return;
}

// For each vendor, report the company name and a maximum 5 customers.
foreach (Company vendor in results.Vendors)
{
    Console.WriteLine("\n{0} customers", vendor);
    Console.WriteLine("---");
    // Use the vendor's API resource name as the parent resource.
    PartnersResource.VendorsResource.CustomersResource.ListRequest customerRequest =
        service.Partners.Vendors.Customers.List(vendor.Name);
    customerRequest.PageSize = 5;
    var customerResponse = customerRequest.Execute();

    IList<Company> customers = customerResponse.Customers;
    if (customers == null)
    {
        Console.WriteLine("No customers");
        break;
    }
    else
    {
        foreach (Company customer in customers)
        {
            Console.WriteLine("{0}: {1}", customer.Name, customer.TermsStatus);
        }
    }
}

Python

# First, get the organization's vendors.
parent_resource = 'partners/{0}'.format(PARTNER_ID)
vendor_response = service.partners().vendors().list(
    parent=parent_resource).execute()
if 'vendors' not in vendor_response:
  return

# For each vendor, report the company name and a maximum 5 customers.
for vendor in vendor_response['vendors']:
  print '\n{0} customers'.format(vendor['companyName'])
  print '---'
  # Use the vendor's API resource name as the parent resource.
  customer_response = service.partners().vendors().customers().list(
      parent=vendor['name'], pageSize=5).execute()
  if 'customers' not in customer_response:
    print 'No customers'
    break
  for customer in customer_response['customers']:
    print '  {0}: {1}'.format(customer['name'], customer['termsStatus'])

如果您販售一系列裝置,可能需要知道哪家經銷商或 供應商已領取裝置。如要取得經銷商 ID (數值) 的數字,請檢查 裝置聲明記錄中的 resellerId 欄位。

貴機構可以取消認領供應商已認領的裝置。對於會修改裝置的其他 API 呼叫,您應在呼叫 API 方法前,確認貴機構已聲明擁有該裝置。以下範例說明如何執行這項操作:

Java

// Get the devices claimed for two customers: one of our organization's
// customers and one of our vendor's customers.
FindDevicesByOwnerRequest body = new FindDevicesByOwnerRequest();
body.setSectionType("SECTION_TYPE_ZERO_TOUCH");
body.setCustomerId(Arrays.asList(resellerCustomerId, vendorCustomerId));
body.setLimit(MAX_PAGE_SIZE);
FindDevicesByOwnerResponse response =
    service.partners().devices().findByOwner(PARTNER_ID, body).execute();
if (response.getDevices() == null) {
  return;
}

for (Device device: response.getDevices()) {
  // Confirm the device was claimed by our reseller and not a vendor before
  // updating metadata in another method.
  for (DeviceClaim claim: device.getClaims()) {
    if (claim.getResellerId() == PARTNER_ID) {
      updateDeviceMetadata(device.getDeviceId());
      break;
    }
  }
}

.NET

// Get the devices claimed for two customers: one of our organization's
// customers and one of our vendor's customers.
FindDevicesByOwnerRequest body = new FindDevicesByOwnerRequest
{
    Limit = MaxPageSize,
    SectionType = "SECTION_TYPE_ZERO_TOUCH",
    CustomerId = new List<long?>
    {
        resellerCustomerId,
        vendorCustomerId
    }
};
var response = service.Partners.Devices.FindByOwner(body, PartnerId).Execute();
if (response.Devices == null)
{
    return;
}

foreach (Device device in response.Devices)
{
    // Confirm the device was claimed by our reseller and not a vendor before
    // updating metadata in another method.
    foreach (DeviceClaim claim in device.Claims)
    {
        if (claim.ResellerId == PartnerId)
        {
            UpdateDeviceMetadata(device.DeviceId);
            break;
        }
    }
}

Python

# Get the devices claimed for two customers: one of our organization's
# customers and one of our vendor's customers.
request_body = {'limit':MAX_PAGE_SIZE, \
  'pageToken':None, \
  'customerId':[reseller_customer_id, vendor_customer_id], \
  'sectionType':'SECTION_TYPE_ZERO_TOUCH'}
response = service.partners().devices().findByOwner(partnerId=PARTNER_ID,
    body=request_body).execute()

for device in response['devices']:
  # Confirm the device was claimed by our reseller and not a vendor before
  # updating metadata in another method.
  for claim in device['claims']:
    if claim['resellerId'] == PARTNER_ID:
      update_device_metadata(device['deviceId'])
      break

長時間執行的批次作業

API 包含非同步版本的裝置方法。 這些方法允許批次處理許多裝置;而 方法則是針對每個 API 要求處理一部裝置非同步方法的名稱 含有「Async」後置字串,例如 claimAsync

非同步 API 方法會在處理程序完成之前傳回結果。 非同步方法也能幫助應用程式 (或工具) 持續回應您的 等待長時間執行的作業完成時。您的應用程式應 請定期檢查作業狀態。

作業

您可以使用 Operation 追蹤長時間執行的批次作業。A 罩杯 成功呼叫非同步方法時,會傳回作業的參照 回應。下列 JSON 程式碼片段顯示了呼叫後的一般回應 updateMetadataAsync:

{
  "name": "operations/apibatchoperation/1234567890123476789"
}

每項作業都包含個別工作清單。致電 operations.get: 作業所含工作的結果。下列程式碼片段說明如何執行這項操作。您必須在自己的應用程式中處理所有錯誤。

Java

// Build out the request body to apply the same order number to a customer's
// purchase of 2 devices.
UpdateMetadataArguments firstUpdate = new UpdateMetadataArguments();
firstUpdate.setDeviceMetadata(metadata);
firstUpdate.setDeviceId(firstTargetDeviceId);

UpdateMetadataArguments secondUpdate = new UpdateMetadataArguments();
secondUpdate.setDeviceMetadata(metadata);
secondUpdate.setDeviceId(firstTargetDeviceId);

// Start the device metadata update.
UpdateDeviceMetadataInBatchRequest body = new UpdateDeviceMetadataInBatchRequest();
body.setUpdates(Arrays.asList(firstUpdate, secondUpdate));
Operation response = service
    .partners()
    .devices()
    .updateMetadataAsync(PARTNER_ID, body)
    .execute();

// Assume the metadata update started, so get the Operation for the update.
Operation operation = service.operations().get(response.getName()).execute();

.NET

// Build out the request body to apply the same order number to a customer's
// purchase of 2 devices.
var updates = new List<UpdateMetadataArguments>
{
    new UpdateMetadataArguments
    {
        DeviceMetadata = metadata,
        DeviceId = firstTargetDeviceId
    },
    new UpdateMetadataArguments
    {
        DeviceMetadata = metadata,
        DeviceId = secondTargetDeviceId
    }
};

// Start the device metadata update.
UpdateDeviceMetadataInBatchRequest body = new UpdateDeviceMetadataInBatchRequest
{
    Updates = updates
};
var response = service.Partners.Devices.UpdateMetadataAsync(body, PartnerId).Execute();

// Assume the metadata update started, so get the Operation for the update.
Operation operation = service.Operations.Get(response.Name).Execute();

Python

# Build out the request body to apply the same order number to a customer's
# purchase of 2 devices.
updates = [{'deviceMetadata':metadata,'deviceId':first_target_device_id},
    {'deviceMetadata':metadata,'deviceId':second_target_device_id}]

# Start the device metadata update.
response = service.partners().devices().updateMetadataAsync(
    partnerId=PARTNER_ID, body={'updates':updates}).execute()

# Assume the metadata update started, so get the Operation for the update.
operation = service.operations().get(name=response['name']).execute()

如要確認作業是否完成,請查看 done 欄位的作業 值為 true。如果缺少 donefalse,表示作業仍在執行 備用資源

回應

作業完成後,API 會使用結果更新作業,即使所有或沒有個別工作成功,也一樣。response 欄位是 DevicesLongRunningOperationResponse 物件,詳細說明作業中每個裝置的處理作業。

檢查 successCount 欄位,即可有效率地找出是否有任何工作失敗,並避免重複處理大型結果清單。的 perDeviceStatus 欄位 DevicesLongRunningOperationResponseOperationPerDevice 執行個體,詳細說明每部裝置 作業。清單順序與原始要求中的任務相符。

每個 OperationPerDevice 工作都包含 result 欄位,以及伺服器收到的要求提醒摘要。確認工作是否成功或失敗 使用 result 欄位。

下方的 JSON 程式碼片段顯示呼叫 updateMetadataAsync 後,作業的部分典型回應:

"response": {
  "perDeviceStatus": [
    {
      "result": {
        "deviceId": "12345678901234567",
        "status": "SINGLE_DEVICE_STATUS_SUCCESS"
      },
      "updateMetadata": {
        "deviceId": "12345678901234567",
        "deviceMetadata": {
          "entries": {
            "phonenumber": "+1 (800) 555-0100"
          }
        }
      }
    }
  ],
  "successCount": 1
}

追蹤進度

如果應用程式需要追蹤進度,您應定期重新擷取作業。metadata 欄位包含一個 DevicesLongRunningOperationMetadata 執行個體,可協助您的應用程式查看執行中作業的最新進度。請使用下表所列 DevicesLongRunningOperationMetadata 的欄位,追蹤作業的進度:

欄位 常見用途
processingStatus 從「BATCH_PROCESS_PENDING」變更為 BATCH_PROCESS_IN_PROGRESS,之後是 BATCH_PROCESS_PROCESSED 表示作業進度。
progress 已處理的更新百分比。應用程式可使用 來估計完成時間由於 progress 值在作業結束時可能為 100,因此請檢查作業的 done 欄位,瞭解作業是否已完成並有結果。
devicesCount 顯示作業的更新次數。如果 API 無法剖析部分更新,這可能與要求中的更新次數不同。

下方的簡化範例說明應用程式如何使用進度中繼資料設定輪詢間隔。在應用程式中,您可能需要更複雜的工作 執行輪詢作業您也需要新增錯誤處理機制。

Java

// Milliseconds between polling the API.
private static long MIN_INTERVAL = 2000;
private static long MAX_INTERVAL = 10000;

// ...
// Start the device metadata update.
Operation response = service
    .partners()
    .devices()
    .updateMetadataAsync(PARTNER_ID, body)
    .execute();
String operationName = response.getName();

// Start polling for completion.
long startTime = new Date().getTime();
while (true) {

  // Get the latest update on the operation's progress using the API.
  Operation operation = service.operations().get(operationName).execute();

  if (operation.get("done") != null && operation.getDone()) {
    // The operation is finished. Print the status.
    System.out.format("Operation complete: %s of %s successful device updates\n",
        operation.getResponse().get("successCount"),
        operation.getMetadata().get("devicesCount"));
    break;

  } else {
    // Estimate how long the operation *should* take - within min and max value.
    BigDecimal opProgress = (BigDecimal) operation.getMetadata().get("progress");
    double progress = opProgress.longValue();
    long interval = MAX_INTERVAL;
    if (progress > 0) {
      interval = (long) ((new Date().getTime() - startTime) *
          ((100.0 - progress) / progress));
    }
    interval = Math.max(MIN_INTERVAL, Math.min(interval, MAX_INTERVAL));

    // Sleep until the operation should be complete.
    Thread.sleep(interval);
  }
}

.NET

// Milliseconds between polling the API.
private static double MinInterval = 2000;
private static double MaxInterval = 10000;

// ...
// Start the device metadata update.
var response = service.Partners.Devices.UpdateMetadataAsync(body, PartnerId).Execute();
var operationName = response.Name;

// Start polling for completion.
var startTime = DateTime.Now;
while (true)
{

    // Get the latest update on the operation's progress using the API.
    Operation operation = service.Operations.Get(operationName).Execute();

    if (operation.Done == true)
    {
        // The operation is finished. Print the status.
        Console.WriteLine("Operation complete: {0} of {1} successful device updates",
                          operation.Response["successCount"],
                          operation.Metadata["devicesCount"]);
        break;
    }
    else
    {
        // Estimate how long the operation *should* take - within min and max value.
        double progress = (double)(long)operation.Metadata["progress"];
        double interval = MaxInterval;
        if (progress > 0)
        {
            interval = DateTime.Now.Subtract(startTime).TotalMilliseconds *
                                     ((100.0 - progress) / progress);
        }
        interval = Math.Max(MinInterval, Math.Min(interval, MaxInterval));

        // Sleep until the operation should be complete.
        System.Threading.Thread.Sleep((int)interval);
    }
}

Python

# Seconds between polling the API.
MIN_INTERVAL = 2;
MAX_INTERVAL = 10;

# ...
# Start the device metadata update
response = service.partners().devices().updateMetadataAsync(
  partnerId=PARTNER_ID, body={'updates':updates}).execute()

op_name = response['name']
start_time = time.time()

# Start polling for completion
while True:
  # Get the latest update on the operation's progress using the API
  op = service.operations().get(name=op_name).execute()

  if 'done' in op and op['done']:
    # The operation is finished. Print the status.
    print('Operation complete: {0} of {1} successful device updates'.format(
      op['response']['successCount'], op['metadata']['devicesCount']
    ))
    break
  else:
    # Estimate how long the operation *should* take - within min and max.
    progress = op['metadata']['progress']
    interval = MIN_INTERVAL
    if progress > 0:
      interval = (time.time() - start_time) * ((100.0 - progress) / progress)
    interval = max(MIN_INTERVAL, min(interval, MAX_INTERVAL))

    # Sleep until the operation should be complete.
    time.sleep(interval)

請選擇適合應用程式使用者的輪詢方法。如果某些應用程式使用者正在等待程序完成,定期提供進度更新資訊可能會對他們有所幫助。

分頁結果

partners.devices.findByOwner API 方法可能會傳回非常大的裝置清單。為了縮減回應大小 其他 API 方法 (例如 partners.devices.findByIdentifier)。 支援分頁結果。使用分頁結果後,應用程式就能逐一要求及處理大型清單。

呼叫 API 方法後,請檢查回應是否包含 nextPageToken。如果 nextPageToken 不是 null,應用程式可以使用該值,透過再次呼叫該方法來擷取另一個裝置頁面。您必須在 limit 參數中設定裝置數量上限。如果 nextPageTokennull,您的應用程式要求 最後一頁。

以下範例方法說明應用程式如何一次列印一頁裝置清單:

Java

private static long MAX_PAGE_SIZE = 10;

// ...
/**
 * Demonstrates how to loop through paginated lists of devices.
 * @param pageToken       The token specifying which result page to return.
 * @throws IOException    If the zero-touch API call fails.
 */
private void printDevices(String pageToken) throws IOException {

  // Create the request body to find the customer's devices.
  FindDevicesByOwnerRequest body = new FindDevicesByOwnerRequest();
  body.setLimit(MAX_PAGE_SIZE);
  body.setSectionType("SECTION_TYPE_ZERO_TOUCH");
  body.setCustomerId(Collections.singletonList(targetCustomerId));

  // Call the API to get a page of Devices. Send a page token from the method
  // argument (might be None). If the page token is None, the API returns the first page.
  FindDevicesByOwnerResponse response =
      service.partners().devices().findByOwner(PARTNER_ID, body).execute();
  if (response.getDevices() == null) {
    return;
  }

  // Print the devices included in this page of results.
  for (Device device: response.getDevices()) {
    System.out.format("Device %s\n", device.getName());
  }
  System.out.println("---");

  // Check to see if another page of devices is available. If yes,
  // fetch and print the devices.
  if (response.getNextPageToken() != null) {
    this.printDevices(response.getNextPageToken());
  }
}

// ...
// Pass null to start printing the first page of devices.
printDevices(null);

.NET

private static int MaxPageSize = 10;

// ...
/// <summary>Demonstrates how to loop through paginated lists of devices.</summary>
/// <param name="pageToken">The token specifying which result page to return.</param>
private void PrintDevices(string pageToken)
{
    // Create the request body to find the customer's devices.
    FindDevicesByOwnerRequest body = new FindDevicesByOwnerRequest
    {
        PageToken = pageToken,
        Limit = MaxPageSize,
        SectionType = "SECTION_TYPE_ZERO_TOUCH",
        CustomerId = new List<long?>
        {
            targetCustomerId
        }
    };

    // Call the API to get a page of Devices. Send a page token from the method
    // argument (might be None). If the page token is None, the API returns the first page.
    var response = service.Partners.Devices.FindByOwner(body, PartnerId).Execute();
    if (response.Devices == null)
    {
        return;
    }

    // Print the devices included in this page of results.
    foreach (Device device in response.Devices)
    {
        Console.WriteLine("Device: {0}", device.Name);
    }
    Console.WriteLine("---");

    // Check to see if another page of devices is available. If yes,
    // fetch and print the devices.
    if (response.NextPageToken != null)
    {
        this.PrintDevices(response.NextPageToken);
    }
}

// ...
// Pass null to start printing the first page of devices.
PrintDevices(null);

Python

MAX_PAGE_SIZE = 10;

# ...
def print_devices(page_token):
  """Demonstrates how to loop through paginated lists of devices.

  Args:
    page_token: The token specifying which result page to return.
  """

   # Create the body to find the customer's devices.
  request_body = {'limit':MAX_PAGE_SIZE, \
    'pageToken':page_token, \
    'customerId':[target_customer_id], \
    'sectionType':'SECTION_TYPE_ZERO_TOUCH'}

  # Call the API to get a page of Devices. Send a page token from the method
  # argument (might be None). If the page token is None,
  # the API returns the first page.
  response = service.partners().devices().findByOwner(partnerId=PARTNER_ID,
    body=request_body).execute()

  # Print the devices included in this page of results.
  for device in response['devices']:
    print 'Device: {0}'.format(device['name'])
  print '---'

  # Check to see if another page of devices is available. If yes,
  # fetch and print the devices.
  if 'nextPageToken' in response:
    print_devices(response['nextPageToken'])

# ...
# Pass None to start printing the first page of devices.
print_devices(None);

後續步驟

現在您已瞭解 API 的運作方式,不妨參考下列的快速入門導覽課程: Java.NETPython。您可以使用 colab 查看 API 呼叫範例,並自行試驗呼叫 API。