How it works


The zero-touch enrollment API helps device resellers automate their integration. Your organization's sales tools can build in zero-touch enrollment—making your users, and your customers, more productive. Use the API to help your users:

  • Assign purchased devices to a customer's zero-touch enrollment account.
  • Create your customer's zero-touch enrollment account.
  • Attach your organization's telephone and order metadata to devices.
  • Create reports about devices assigned to your customers.

This document introduces the API and explains the patterns. If you want to explore the API yourself, see Get started.

API concepts

Customers and devices are the core resources you use in the API. To create customers, call create. You can create devices using the claim API methods (see below). Your organization can also create customers and devices using the zero-touch enrollment portal.

Device and customer resource relationship

Companies that your organization sell devices to. Customers have a name and an ID. Use a customer when you want to claim or find their devices. To learn more, see Customer.
A zero-touch enrollment-capable Android device your organization sells to a customer. Devices have hardware IDs, metadata, and customer claims. Devices are central to the API, so you use them in almost all methods. To learn more, see Device.
Encapsulates hardware IDs, such as IMEI or MEID, to identify a manufactured device. Use a DeviceIdentifier to target the device you want to find, update, or claim. To learn more, read Identifiers.
Stores key-value pairs of metadata for the device. Use DeviceMetadata to store your organization's metadata. To learn more, read Device metadata.

To list all the API methods and resources your app can use, see the API Reference.

Create customers

You can call the create API method to create customer accounts for zero-touch enrollment. Because your customers see the company name in their zero-touch enrollment portal, your app's user should confirm that it's correct. You can't edit a customer's name after you create the customer.

You need to include at least one corporate email address, associated with a Google Account, to be the owner. You can't use personal Gmail accounts with the API. If the customer needs help associating the account, send the instructions from Associate a Google Account.

After you create a customer by calling the API, they manage their employees' portal access—you can't edit your customers' users using the API. The Python snippet below shows how you might create a customer:

# Provide the customer data as a Company type
company = {'companyName':'XYZ Corp', \
  'ownerEmails':['', ''], \

# Set the reseller ID as the partner
parent_resource = 'partners/{0}'.format(MY_PARTNER_ID)

# Create the customer using the values in the company
results =,

The API doesn't notify your customer that they have access. Typically, your organization contacts the customer to tell them about the portal. You might want to send them a link to the portal so that they can manage their users. To learn more about the owner and admin roles for employees of your customer, read Portal users.

Claim devices for customers

After your customers purchase devices, they'll want to configure provisioning settings for these devices in their account. Claiming a device adds the device to zero-touch enrollment and shows the device in the customer's view of the portal.

A device's provisioning record has a section for zero-touch enrollment. You assign the device by claiming the record's zero-touch enrollment section for a customer. Call the partners.devices.claim or partners.devices.claimAsync methods with the customer as an argument. Always supply SECTION_TYPE_ZERO_TOUCH as a value for sectionType.

You'll need to unclaim (see below) a customer's device before you can claim the same device for a different customer. The claim methods validate the DeviceIdentifier fields, including the IMEI number and manufacturer name, when creating a new device.

The Python snippet below shows how to claim a device:

# Identify the device to claim
device_identifier = {'manufacturer':'Google', \
 'model':'Pixel', 'imei':'123456789012347'}

# Create the body to connect the customer with the device
request_body = {'deviceIdentifier':device_identifier, \
 'customerId':TARGET_CUSTOMER, \

# Claim the device
results =,

Unclaiming devices

Your organization can unclaim a device from a customer. Unclaiming a device removes it from zero-touch enrollment. A reseller might unclaim a device that they want migrated to another account, returned, or that was mistakenly claimed. Call the method partners.devices.unclaim or partners.devices.unclaimAsync to unclaim a device from a customer.

Long-running batch operations

The API includes asynchronous versions of the device methods. These methods allow batch processing of many devices, while the synchronous methods process one device for each API request. The asynchronous method names have an Async suffix, for example claimAsync.

Asynchronous API methods return a result before the processing is complete. Asynchronous methods also help your app (or tool) remain responsive for your users while they wait for a long-running operation to complete. Your app should check the status of the operation periodically.


You use an Operation to track a long-running batch operation. A successful call to an asynchronous method returns a reference to the operation in the response. The JSON snippet below shows a typical response after calling updateMetadataAsync:

  "name": "operations/apibatchoperation/1234567890123476789"

Each operation contains a list of individual tasks. Call operations.get to find out information about the status and results of tasks contained in the operation. The Python snippet below shows how you might do this. In your own app, you'll need to handle any errors.

# Build out the request body using a list of updates.
updates = [{'deviceMetadata':metadata,'deviceId':TARGET_DEVICE_ID}]

# Start the device metadata update.
results =
partnerId=MY_PARTNER_ID, body={'updates':updates}).execute()

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

To find out if an operation finished, check the operation for a done field with a value of true. If done is missing or false, the operation is still running.


After an operation finishes, the API updates the operation with the result—even if all or none of the individual tasks are successful. The response field is a DevicesLongRunningOperationResponse object detailing the processing of each device in the operation.

Inspect the successCount field to efficiently find out if any tasks failed and avoid iterating through large result lists. The perDeviceStatus field of DevicesLongRunningOperationResponse is a list of OperationPerDevice instances detailing each device in the operation. The list order matches the tasks in the original request.

Each OperationPerDevice task contains a result field and a reminder summary of the request received by the server. Check if the task succeeded or failed using the result field.

The JSON snippet below shows part of a typical response from an operation after a call to updateMetadataAsync:

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

Track progress

If your app needs to track progress, you should periodically refetch the operation. The metadata field contains a DevicesLongRunningOperationMetadata instance to help your app check the latest progress of a running operation. Use the fields of DevicesLongRunningOperationMetadata listed in the following table to track the operation's progress.

Field Typical use
processingStatus Changes from BATCH_PROCESS_PENDING to BATCH_PROCESS_IN_PROGRESS, and then to BATCH_PROCESS_PROCESSED as the operation progresses.
progress The percentage of updates processed. Your app can use this to estimate a finish time. Because the progress value can be 100 while the operation is finishing up, check the done field of an operation to know if it finished and has a result.
devicesCount Shows the number of updates in the operation. This might be different from the number of updates in your request if the API can't parse some of the updates.

The simplified Python example below shows how an app might use the progress metadata to set polling intervals. In your app, you might need a more sophisticated task runner for polling. You'll also need to add error handling.


# ...

# Start the device metadata update
results =
  partnerId=MY_PARTNER_ID, body={'updates':updates}).execute()

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

# Start polling for completion
while True:
  # Get the latest update on the operation's progress using the API
  op = provisioning.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']
    # Estimate how long the operation *should* take - within min and max value
    progress = op['metadata']['progress']
    interval = (time.time() - start_time) * ((100.0 - progress) / progress)
    interval = max(MIN_INTERVAL, min(interval, MAX_INTERVAL))

    # Sleep until the operation should be complete.

Choose a polling approach that makes sense for your app's users. Some app users might benefit from regular progress updates if they're waiting for a process to complete.

Paged results

The partners.devices.findByOwner API method might return very large lists of devices. To reduce the response size, this and other API methods (such as partners.devices.findByIdentifier) support paged results. With paged results, your application can iteratively request and process large lists one page at a time.

After calling the API method, check if the response includes a value for nextPageToken. If nextPageToken isn't null, your app can use it to fetch another page of devices by calling the method again. You need to set an upper limit for the number of devices in the limit parameter. If nextPageToken is null, your app has requested the last page.

The Python example method below shows how your app might print a list of devices, one page at a time:


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

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

  # 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.
  results =,

  # Print the devices included in this page of results.
  for device in results['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 results:


Next steps

Now that you know how the API works, read Get started to set up authorization and try out the examples.


Android zero-touch enrollment