Cómo funciona

Introducción

La API de inscripción automática ayuda a los revendedores de dispositivos a automatizar su integración. Las herramientas de ventas de tu organización pueden compilar con inscripción automática, lo que permite que tus usuarios y clientes sean más productivos. Usa la API para ayudar a tus usuarios a hacer lo siguiente:

  • Asignar los dispositivos comprados a la cuenta de inscripción automática de un cliente
  • Crear la cuenta de inscripción automática de tu cliente
  • Adjunta los metadatos del teléfono y de los pedidos de tu organización a los dispositivos.
  • Crear informes sobre los dispositivos asignados a tus clientes

En este documento, se presenta la API y se explican los patrones. Si quieres explorar la API tú mismo, prueba una guía de inicio rápido para Java, .NET o Python.

Conceptos de la API

Los clientes y los dispositivos son los recursos principales que usas en la API. Para crear clientes, llama a create. Puedes crear dispositivos con los métodos de la API de reclamos (consulta a continuación). Tu organización también puede crear clientes y dispositivos con el portal de inscripción automática.

Relación entre el dispositivo y los recursos del cliente

Cliente
Empresas a las que tu organización vende dispositivos. Los clientes tienen un name y un ID. Atiende a un cliente cuando quieras reclamar o encontrar sus dispositivos. Para obtener más información, consulta Customer.
Dispositivo
Un dispositivo Android o ChromeOS compatible con la inscripción automática que tu organización vende a un cliente. Los dispositivos tienen IDs de hardware, metadatos y reclamos de los clientes. Los dispositivos son fundamentales para la API, por lo que los usas en casi todos los métodos. Para obtener más información, consulta Device.
DeviceIdentifier
Encapsula los IDs de hardware, como IMEI o MEID, para identificar un dispositivo fabricado. Usa un DeviceIdentifier para orientar al dispositivo que quieres encontrar, actualizar o reclamar. Para obtener más información, consulta Identificadores.
DeviceMetadata
Almacena pares clave-valor de metadatos para el dispositivo. Usa DeviceMetadata para almacenar los metadatos de tu organización. Para obtener más información, consulta Metadatos del dispositivo.

Para enumerar todos los métodos y recursos de API que puede usar tu app, consulta la Referencia de la API.

Crear clientes

En el caso de los dispositivos Android, el revendedor es responsable de crear la cuenta del cliente en su nombre. El cliente usará esta cuenta para acceder al portal de inscripción automática a fin de configurar la configuración de aprovisionamiento de sus dispositivos. Esto no es necesario para los dispositivos ChromeOS, que ya tienen una cuenta de Google Workspace que usarán para configurar sus parámetros de aprovisionamiento.

Puedes llamar al método de la API create a fin de crear cuentas de clientes para la inscripción automática. Debido a que los clientes ven el nombre de la empresa en su portal de inscripción automática, el usuario de la app debe confirmar que es correcto. No puedes editar el nombre de un cliente después de crearlo.

Debes incluir al menos una dirección de correo electrónico empresarial, asociada con una Cuenta de Google, para ser el propietario. No puedes usar cuentas personales de Gmail con la API. Si el cliente necesita ayuda para asociar la cuenta, envía las instrucciones desde Asocia una Cuenta de Google.

Después de crear un cliente con una llamada a la API, este administra el acceso al portal de sus empleados. No puedes editar los usuarios de tus clientes con la API. En el siguiente fragmento, se muestra cómo puedes crear un cliente:

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()

Para obtener más información sobre las funciones de propietario y administrador de los empleados de tu cliente, consulta Usuarios de portal.

Reclamar dispositivos para los clientes

Después de que tus clientes compren dispositivos, querrán establecer la configuración de aprovisionamiento de estos dispositivos en su cuenta. Reclamar un dispositivo agrega el dispositivo a la inscripción automática y le brinda al cliente la capacidad de configurar los parámetros de aprovisionamiento.

El registro de aprovisionamiento de un dispositivo tiene una sección para la inscripción automática. Para asignar el dispositivo, debes reclamar la sección de inscripción automática del registro para un cliente. Llama a los métodos partners.devices.claim o partners.devices.claimAsync con el cliente como argumento. Siempre proporciona SECTION_TYPE_ZERO_TOUCH como valor para sectionType.

Deberás retirar el reclamo del dispositivo de un cliente (consulta a continuación) antes de poder reclamar el mismo dispositivo para otro cliente. Los métodos de reclamación validate los campos DeviceIdentifier, incluidos el IMEI o MEID, el número de serie, el nombre del fabricante y el modelo, y el ID de dispositivo certificado para los dispositivos ChromeOS cuando se crea un dispositivo nuevo.

En el siguiente fragmento, se muestra cómo reclamar un dispositivo:

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()

Rechazando dispositivos

Tu organización puede retirar un reclamo de un dispositivo de un cliente. Si retiras un dispositivo, se quitará de la inscripción automática. Un revendedor podría retirar un dispositivo que quiere migrar a otra cuenta, devolver o que se reclamó por error. Llama al método partners.devices.unclaim o partners.devices.unclaimAsync para retirar un dispositivo de un cliente.

Proveedores

Puedes usar proveedores para representar a los socios revendedores en tu red de concesionarios, a operadores locales dentro de una red de revendedores global o a cualquier organización que venda dispositivos en tu nombre. Los proveedores te ayudan a separar a tus usuarios, clientes y dispositivos:

  • Los proveedores que creas no pueden ver tu cuenta de inscripción automática ni las cuentas de los demás.
  • Puedes ver los clientes y dispositivos de tus proveedores y cancelar el registro de los dispositivos de los proveedores. Sin embargo, no puedes asignar dispositivos a los clientes de tus proveedores.

Usa el portal a fin de crear proveedores para tu organización; no puedes usar la API. Para crear un proveedor nuevo, el rol de tu cuenta debe ser Propietario. Si tu organización tiene proveedores, puedes llamar a partners.vendors.list para enumerarlos y a partners.vendors.customers.list para obtener los clientes de tu proveedor. En el siguiente ejemplo, se usan ambos métodos para imprimir un informe que muestre el estado de las Condiciones del Servicio de los clientes de los proveedores:

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'])

Si tienes una colección de dispositivos, es posible que necesites saber qué revendedor o proveedor reclamó el dispositivo. Para obtener el ID numérico del revendedor, inspecciona el valor del campo resellerId en el registro de reclamación de un dispositivo.

Tu organización puede retirar un dispositivo reclamado por el proveedor. Para otras llamadas a la API que modifican dispositivos, debes verificar que tu organización haya reclamado el dispositivo antes de llamar al método de la API. En el siguiente ejemplo, se muestra cómo hacerlo:

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

Operaciones por lotes de larga duración

La API incluye versiones asíncronas de los métodos del dispositivo. Estos métodos permiten el procesamiento por lotes de muchos dispositivos, mientras que los métodos síncronos procesan un dispositivo para cada solicitud a la API. Los nombres de los métodos asíncronos tienen el sufijo Async, por ejemplo, claimAsync.

Los métodos asíncronos de la API muestran un resultado antes de que se complete el procesamiento. Los métodos asíncronos también ayudan a que tu app (o herramienta) siga siendo responsiva para los usuarios mientras esperan a que se complete una operación de larga duración. Tu app debe verificar el estado de la operación periódicamente.

Operaciones

Usa un Operation para realizar el seguimiento de una operación por lotes de larga duración. Una llamada exitosa a un método asíncrono muestra una referencia a la operación en la respuesta. En el siguiente fragmento de JSON, se muestra una respuesta típica después de llamar a updateMetadataAsync:

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

Cada operación contiene una lista de tareas individuales. Llama a operations.get para obtener información sobre el estado y los resultados de las tareas incluidas en la operación. En el siguiente fragmento, se muestra cómo hacerlo. En tu propia app, deberás controlar los errores.

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()

Para saber si finalizó una operación, revisa la operación en un campo done con un valor de true. Si falta done o false, la operación aún se está ejecutando.

Respuestas

Cuando finaliza una operación, la API actualiza la operación con el resultado, incluso si todas o ninguna de las tareas individuales se realizaron de forma correcta. El campo response es un objeto DevicesLongRunningOperationResponse que detalla el procesamiento de cada dispositivo en la operación.

Inspecciona el campo successCount para determinar de manera eficiente si alguna tarea falló y evita la iteración a través de listas de resultados grandes. El campo perDeviceStatus de DevicesLongRunningOperationResponse es una lista de instancias de OperationPerDevice en la que se detalla cada dispositivo en la operación. El orden de la lista coincide con las tareas de la solicitud original.

Cada tarea OperationPerDevice contiene un campo result y un resumen de recordatorios de la solicitud que recibió el servidor. Verifica si la tarea se realizó correctamente o si falló en el campo result.

En el siguiente fragmento JSON, se muestra parte de una respuesta típica de una operación después de una llamada a updateMetadataAsync:

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

Realice un seguimiento del progreso

Si tu app necesita hacer un seguimiento del progreso, debes recuperar la operación de forma periódica. El campo metadata contiene una instancia de DevicesLongRunningOperationMetadata para ayudar a tu app a verificar el progreso más reciente de una operación en ejecución. Usa los campos de DevicesLongRunningOperationMetadata que se indican en la siguiente tabla para realizar un seguimiento del progreso de la operación:

Campo Uso típico
processingStatus Cambia de BATCH_PROCESS_PENDING a BATCH_PROCESS_IN_PROGRESS y, luego, a BATCH_PROCESS_PROCESSED a medida que avanza la operación.
progress El porcentaje de actualizaciones procesadas. Tu app puede usar esto para estimar una hora de finalización. Debido a que el valor progress puede ser 100 mientras finaliza la operación, verifica el campo done de una operación para saber si finalizó y tiene un resultado.
devicesCount Muestra la cantidad de actualizaciones en la operación. Esto puede ser diferente de la cantidad de actualizaciones en tu solicitud si la API no puede analizar algunas de las actualizaciones.

En el siguiente ejemplo simplificado, se muestra cómo una app podría usar los metadatos de progreso para establecer intervalos de sondeo. En tu app, es posible que necesites un ejecutor de tareas más sofisticado para los sondeos. También deberás agregar el manejo de errores.

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)

Elige un enfoque de encuesta que sea adecuado para los usuarios de tu app. Algunos usuarios de la app pueden beneficiarse de las actualizaciones de progreso periódicas si esperan que se complete un proceso.

Resultados paginados

Es posible que el método de la API partners.devices.findByOwner muestre listas muy grandes de dispositivos. Para reducir el tamaño de la respuesta, este y otros métodos de la API (como partners.devices.findByIdentifier) admiten resultados paginados. Con los resultados paginados, tu aplicación puede solicitar y procesar listas grandes de forma iterativa, una página a la vez.

Después de llamar al método de la API, verifica si la respuesta incluye un valor para nextPageToken. Si nextPageToken no es null, tu app puede usarlo para recuperar otra página de dispositivos llamando nuevamente al método. Debes establecer un límite superior para la cantidad de dispositivos en el parámetro limit. Si nextPageToken es null, tu app solicitó la última página.

En el método de ejemplo que aparece a continuación, se muestra cómo tu app podría imprimir una lista de dispositivos, una página a la vez:

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);

Próximos pasos

Ahora que sabes cómo funciona la API, prueba los ejemplos con una guía de inicio rápido para Java, .NET o Python.