簡介
零接觸註冊機制 API 可協助裝置經銷商自動化整合作業。貴機構的銷售工具可在零接觸註冊機制中建構,讓使用者和客戶提升工作效率。運用 API 協助使用者:
- 將購買的裝置指派給客戶的零接觸註冊機制帳戶。
- 建立客戶的零接觸註冊機制帳戶。
- 將貴機構的電話和訂單中繼資料附加至裝置。
- 針對指派給客戶的裝置建立報表。
本文件將介紹這個 API,並說明這些模式。如果您想自行探索 API,請參考 Java、.NET 或 Python 快速入門導覽課程。
API 概念
客戶和裝置是您在 API 中使用的核心資源。如要建立客戶,請呼叫 create
。您可以使用憑證附加資訊 API 方法建立裝置 (請見以下說明)。貴機構也可以使用零接觸註冊機制入口網站建立客戶和裝置。
- 客戶
- 貴機構販售裝置的公司。客戶擁有
name
和ID
。想聲明擁有權或尋找他們的裝置時,請使用客戶。詳情請參閱Customer
。 - 裝置
- 貴機構須使用零接觸註冊機制的 Android 或 ChromeOS 裝置,並販售給客戶。裝置具有硬體 ID、中繼資料和客戶憑證附加資訊。裝置是 API 的核心,因此幾乎所有方法都能使用。詳情請參閱
Device
。 - DeviceIdentifier
- 封裝硬體 ID (例如 IMEI 或 MEID),以便識別製造裝置。使用
DeviceIdentifier
以指定要尋找、更新或聲明擁有權的裝置。詳情請參閱 ID。 - DeviceMetadata
- 儲存裝置中繼資料的鍵/值組合。使用
DeviceMetadata
儲存機構的中繼資料。詳情請參閱裝置中繼資料。
如要列出應用程式可使用的所有 API 方法和資源,請參閱 API 參考資料。
建立客戶
針對 Android 裝置,經銷商負責代表客戶建立客戶帳戶。客戶會使用這個帳戶存取零接觸入口網站,並調整裝置的佈建設定。ChromeOS 裝置已擁有 Google Workspace 帳戶,因此不需要進行這項設定,因為裝置會用來調整佈建設定。
您可以呼叫 create
API 方法,為零接觸註冊機制建立客戶帳戶。由於客戶會在零接觸註冊機制入口網站中看到公司名稱,因此應用程式使用者應確認名稱正確無誤。客戶建立完成後,您就無法編輯客戶名稱。
您至少必須包含一個與 Google 帳戶相關聯的公司電子郵件地址,才能成為擁有者。您無法搭配個人 Gmail 帳戶使用 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.claim
或 partners.devices.claimAsync
方法,做為引數提供給客戶。請一律提供 SECTION_TYPE_ZERO_TOUCH
做為 sectionType
的值。
您必須先取消認領客戶的裝置 (詳見下文),才能為其他客戶領取同一部裝置。這種聲明方法會在建立新裝置時validate 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
追蹤長時間執行的批次作業。若呼叫非同步方法成功,會在回應中傳回作業的參照。下列 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()
如要確認作業是否已完成,請查看作業中是否有值為 true
的 done
欄位。如果缺少 done
或 false
,表示作業仍在執行中。
回應
作業完成後,即使所有個別工作全部或完全沒有成功,API 仍會根據結果更新作業。response
欄位是 DevicesLongRunningOperationResponse
物件,用於詳細說明作業中每個裝置的處理方式。
檢查 successCount
欄位可有效得知是否有任何工作失敗,並避免反覆查看大型結果清單。DevicesLongRunningOperationResponse
的 perDeviceStatus
欄位是 OperationPerDevice
例項清單,其中詳細列出作業中的每部裝置。清單順序與原始要求中的工作相符。
每項 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 及其他 API 方法 (例如 partners.devices.findByIdentifier
) 支援分頁結果。使用分頁結果時,應用程式可以反覆要求及處理一個頁面的大清單。
呼叫 API 方法後,請檢查回應是否包含 nextPageToken
值。如果 nextPageToken
不是 null
,應用程式可再次呼叫該方法,以使用其擷取另一頁。您必須在 limit
參數中設定裝置數量上限。如果 nextPageToken
為 null
,表示應用程式要求最後一頁。
以下範例方法顯示應用程式如何輸出裝置清單,一次一個頁面:
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);