This document introduces the API and explains the patterns. If you want to
explore the API yourself, try a quickstart for
Java,
.NET, or
Python.

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.

Customer

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.

Device

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.

DeviceIdentifier

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.

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.

Note: The API returns an error when one or more of the email addresses isn't
associated with a Google Account. When this happens, ask your user to check
that there's a Google Account
for each email address. Google doesn't provide an API to check if an email
address is associated with 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 snippet
below shows how you might create a customer:

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

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

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.

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.

Caution: Consider prompting your app's user to confirm that they have the
correct device before calling unclaim APIs. Unclaiming a device removes the
customer's provisioning setup and the device becomes unmanaged after a factory
reset.

Vendors

You can use vendors to represent reseller partners in your dealer network, local
operators within a global reseller network, or any organization that sells
devices on your behalf. Vendors help you separate your users, customers, and
devices:

Vendors you create can’t see your zero-touch enrollment account or each
others’ accounts.

You can view your vendors’ customers and devices and you can unregister
vendors’ devices. However, you can’t assign devices to your vendors’ customers.

Key Point: A vendor is a special type of reseller. Vendors appear and behave
(in the portal and APIs) just as a reseller does—except that a vendor can't have
other vendors.

Use the portal to create to create vendors
for your organization—you can’t use the API. Your account role must be Owner
to create a new vendor. If your organization has vendors, you can call
partners.vendors.list to list your vendors and
partners.vendors.customers.list to get your
vendor’s customers. The following example uses both of these methods to print a
report showing the terms of service status for the vendors’ customers:

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

If you have a collection of devices, you might need to know which reseller or
vendor claimed the device. To get the numeric reseller ID, inspect the value of
the resellerId field in a device’s claim record.

Your organization can unclaim a vendor-claimed device. For other API calls that
modify devices, you should check that your organization claimed the device
before calling the API method. The following example shows how you can do this:

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

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.

Operations

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 snippet below shows how you
might do this. In your own app, you'll need to handle any errors.

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

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.

Responses

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:

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 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.

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 example method below shows how your app might print a list of devices, one
page at a time:

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

Next steps

Now that you know how the API works, try out the examples with a quickstart for
Java,
.NET, or
Python.