Codelab: Provision a customer from end-to-end

Before You Begin

If you haven't already done so, you should follow the introduction guide to set up a cloud project and create the service account you'll use for calling Google's APIs.

Overview

Properly provisioning a customer involves several co-dependent steps that span across multiple APIs in the G Suite platform. At a high level, these steps are:

Image Not Found

Step 1: Create service objects with authenticated credentials

To get started with any Google API, you will first need to set up authentication and credentials from within your application. The Google Client Libraries handle this on your behalf. All of the libraries have patterns for creating a credentials object, which can be granted access to all of the APIs and passed into each service. An application should typically have a single set of credentials and use only one cloud project for all Google API interactions.

Python

import sys
from oauth2client.service_account import ServiceAccountCredentials
from apiclient.discovery import build
from apiclient.http import httplib2
from apiclient.http import HttpError

############## REPLACE WITH YOUR OWN VALUES ####################
JSON_PRIVATE_KEY_FILE = 'path/to/json_key_file.json'
RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com'
CUSTOMER_DOMAIN = 'customerdomain.com'
################################################################

# Full List of scopes:
# https://developers.google.com/identity/protocols/googlescopes
OAUTH2_SCOPES = [
    'https://www.googleapis.com/auth/apps.order',
    'https://www.googleapis.com/auth/siteverification',
    'https://www.googleapis.com/auth/admin.directory.user',
]

credentials = ServiceAccountCredentials.from_json_keyfile_name(
                JSON_PRIVATE_KEY_FILE,
                OAUTH2_SCOPES
              ).create_delegated(RESELLER_ADMIN_USER)

reseller_service = build(serviceName='reseller',
                         version='v1',
                         credentials=credentials,
                         http=httplib2.Http())

directory_service = build(serviceName='admin',
                          version='directory_v1',
                          credentials=credentials,
                          http=httplib2.Http())

verification_service = build(serviceName='siteVerification',
                             version='v1',
                             credentials=credentials,
                             http=httplib2.Http())

Java

// OAuth2 and HTTP
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpResponseException;
// Reseller API
import com.google.api.services.reseller.*;
import com.google.api.services.reseller.model.*;
// Directory API
import com.google.api.services.admin.directory.*;
import com.google.api.services.admin.directory.model.User;
import com.google.api.services.admin.directory.model.UserName;
import com.google.api.services.admin.directory.model.UserMakeAdmin;
// Site Verification API
import com.google.api.services.siteVerification.*;
import com.google.api.services.siteVerification.model.*;
// Java library imports
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.List;

public class CodelabExample {
  // Full List of scopes:
  // https://developers.google.com/identity/protocols/googlescopes
  private static final List<String> OAUTH2_SCOPES = Arrays.asList(
    ResellerScopes.APPS_ORDER,
    SiteVerificationScopes.SITEVERIFICATION,
    DirectoryScopes.ADMIN_DIRECTORY_USER
  );

  /***************** REPLACE WITH YOUR OWN VALUES ********************************/
  public static final String JSON_PRIVATE_KEY_FILE = "jsonprivatekey.json";
  public static final String RESELLER_ADMIN_USER = "admin@yourresellerdomain.com";
  public static final String CUSTOMER_DOMAIN = "customerdomain.com";
  /*******************************************************************************/

  public static void main(String[] args)
      throws IOException, GeneralSecurityException, FileNotFoundException {
    // Instantiate services with authenticated credentials
    GoogleCredential jsonCredentials = GoogleCredential
      .fromStream(new FileInputStream(JSON_PRIVATE_KEY_FILE));
    GoogleCredential credentials = new GoogleCredential.Builder()
      .setTransport(GoogleNetHttpTransport.newTrustedTransport())
      .setJsonFactory(JacksonFactory.getDefaultInstance())
      .setServiceAccountScopes(OAUTH2_SCOPES)
      .setServiceAccountUser(RESELLER_ADMIN_USER)
      .setServiceAccountPrivateKey(jsonCredentials.getServiceAccountPrivateKey())
      .setServiceAccountId(jsonCredentials.getServiceAccountId())
      .build();

    Reseller resellerService = new Reseller.Builder(
        credentials.getTransport(),
        credentials.getJsonFactory(),
        credentials).setApplicationName("G Suite Creator").build();

    Directory directoryService = new Directory.Builder(
        credentials.getTransport(),
        credentials.getJsonFactory(),
        credentials).setApplicationName("G Suite Creator").build();

    SiteVerification verificationService = new SiteVerification.Builder(
        credentials.getTransport(),
        credentials.getJsonFactory(),
        credentials).setApplicationName("G Suite Creator").build();
  }
}

PHP

// https://developers.google.com/api-client-library/php/
require_once "vendor/autoload.php";

// Full List of scopes:
// https://developers.google.com/identity/protocols/googlescopes
$OAUTH2_SCOPES = array(
  Google_Service_Reseller::APPS_ORDER,
  Google_Service_SiteVerification::SITEVERIFICATION,
  Google_Service_Directory::ADMIN_DIRECTORY_USER,
);

######### REPLACE WITH YOUR OWN VALUES ###############
$JSON_PRIVATE_KEY_FILE = "path/to/json_key_file.json";
$RESELLER_ADMIN_USER = "admin@yourresellerdomain.com";
$CUSTOMER_DOMAIN = "customerdomain.com";
######################################################

$client = new Google_Client();
$client->setAuthConfig($JSON_PRIVATE_KEY_FILE);
$client->setSubject($RESELLER_ADMIN_USER);
$client->setScopes($OAUTH2_SCOPES);

$resellerService = new Google_Service_Reseller($client);
$directoryService = new Google_Service_Directory($client);
$verificationService = new Google_Service_SiteVerification($client);

Ruby

require 'googleauth'
require 'google/apis/reseller_v1'
require 'google/apis/site_verification_v1'
require 'google/apis/admin_directory_v1'

# Full List of scopes:
# https://developers.google.com/identity/protocols/googlescopes
OAUTH2_SCOPES = [
  'https://www.googleapis.com/auth/apps.order',
  'https://www.googleapis.com/auth/admin.directory.user',
  'https://www.googleapis.com/auth/siteverification',
]

####### REPLACE WITH YOUR OWN VALUES ###############
JSON_PRIVATE_KEY_FILE = 'path/to/json_key_file.json'
RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com'
CUSTOMER_DOMAIN = 'customerdomain.com'
####################################################

credentials = Google::Auth::ServiceAccountCredentials.make_creds(
  json_key_io: File.open(JSON_PRIVATE_KEY_FILE),
  scope: OAUTH2_SCOPES)
credentials.sub = RESELLER_ADMIN_USER

Google::Apis::RequestOptions.default.authorization = credentials

reseller_service = Google::Apis::ResellerV1::ResellerService.new
directory_service = Google::Apis::AdminDirectoryV1::DirectoryService.new
verification_service = Google::Apis::SiteVerificationV1::SiteVerificationService.new

Step 2: Begin domain verification process (Finished in Step 6)

Retrieve a site verification token

A site verification token can be retrieved from the Site Verification API. It is not currently possible to determine if a domain has been previously validated. Customers may be validated via multiple mechanisms with no side effects.

For the type INET_DOMAIN, the following verificationMethod parameters may be used:

  • DNS_TXT
  • DNS_CNAME

A token retrieval example using an INET_DOMAIN type:

Python

# Retrieve the site verification token and place it according to:
# https://developers.google.com/site-verification/v1/getting_started#tokens
response = verification_service.webResource().getToken(
    body={
        'site': {
            'type': 'INET_DOMAIN',
            'identifier': CUSTOMER_DOMAIN
        },
        'verificationMethod': 'DNS_TXT'
    }
).execute()
print response

Java

    // Retrieve the site verification token and place it according to:
    // https://developers.google.com/site-verification/v1/getting_started#tokens
    SiteVerificationWebResourceGettokenRequest.Site getTokenSite =
        new SiteVerificationWebResourceGettokenRequest.Site()
            .setType("INET_DOMAIN")
            .setIdentifier(CUSTOMER_DOMAIN);

    SiteVerificationWebResourceGettokenRequest request =
        new SiteVerificationWebResourceGettokenRequest()
            .setVerificationMethod("DNS_TXT")
            .setSite(getTokenSite);

    SiteVerificationWebResourceGettokenResponse getTokenResponse =
        verificationService.webResource().getToken(request).execute();
    System.out.println("Site Verification Token: " + getTokenResponse.getToken());

PHP

// Retrieve the site verification token and place it according to:
// https://developers.google.com/site-verification/v1/getting_started#tokens
$body = new Google_Service_SiteVerification_SiteVerificationWebResourceGettokenRequest(array(
  "verificationMethod" => "DNS_TXT",
  "site" => array(
    "type" => "INET_DOMAIN",
    "identifier" => $CUSTOMER_DOMAIN
  )
));
$response = $verificationService->webResource->getToken($body);
print_r($response);

Ruby

# Retrieve the site verification token and place it according to:
# https://developers.google.com/site-verification/v1/getting_started#tokens
request = Google::Apis::SiteVerificationV1::GetWebResourceTokenRequest.new(
  site: {
    type: 'INET_DOMAIN',
    identifier: CUSTOMER_DOMAIN
  },
  verification_method: 'DNS_TXT'
)

response = verification_service.get_web_resource_token(request)
puts response.inspect

For the type SITE, the following verificationMethod parameters may be used:

  • FILE
  • META

A token retrieval example using a SITE type with the FILE verification method:

Python

# Retrieve the site verification token and place it according to:
# https://developers.google.com/site-verification/v1/getting_started#tokens
response = verification_service.webResource().getToken(
    body={
        'site': {
            'type': 'SITE',
            'identifier': CUSTOMER_DOMAIN
        },
        'verificationMethod': 'FILE'
    }
).execute()
print response

Java

    // Retrieve the site verification token and place it according to:
    // https://developers.google.com/site-verification/v1/getting_started#tokens
    SiteVerificationWebResourceGettokenRequest.Site getTokenSite =
        new SiteVerificationWebResourceGettokenRequest.Site()
            .setType("SITE")
            .setIdentifier(CUSTOMER_DOMAIN);

    SiteVerificationWebResourceGettokenRequest request =
        new SiteVerificationWebResourceGettokenRequest()
            .setVerificationMethod("FILE")
            .setSite(getTokenSite);
            
    SiteVerificationWebResourceGettokenResponse getTokenResponse = 
        verificationService.webResource().getToken(request).execute();
    System.out.println("Site Verification Token: " + getTokenResponse.getToken());

PHP

// Retrieve the site verification token and place it according to:
// https://developers.google.com/site-verification/v1/getting_started#tokens
$body = new Google_Service_SiteVerification_SiteVerificationWebResourceGettokenRequest(array(
  "verificationMethod" => "FILE",w
  "site" => array(
    "type" => "SITE",
    "identifier" => $CUSTOMER_DOMAIN
  )
));
$response = $verificationService->webResource->getToken($body);
print_r($response);

Ruby

# Retrieve the site verification token and place it according to:
# https://developers.google.com/site-verification/v1/getting_started#tokens
request = Google::Apis::SiteVerificationV1::GetWebResourceTokenRequest.new(
  site: {
    type: 'SITE',
    identifier: CUSTOMER_DOMAIN
  },
  verification_method: 'FILE'
)

response = verification_service.get_web_resource_token(request)
puts response.inspect

Place site verification token in DNS record or site

Once a site verification token has been retrieved, it can be placed on the site or DNS records as described on the Site Verification API documentation.

Step 3: Create a customer with the Reseller API

Determine if a customer exists already in G Suite

Resellers can use the Customers.Get method of the Reseller API to determine if a customer exists in G Suite already. The customer resource returns an HTTP 404 error code if the customer doesn't exist.

Python

# Determine if customer domain already has G Suite
try:
  response = reseller_service.customers().get(
    customerId=CUSTOMER_DOMAIN).execute()
  print "Customer already exists if call succeeds"
  sys.exit()
except HttpError as error:
  if int(error.resp['status']) == 404:
    print "Domain available for G Suite creation"
  else:
    raise

Java

    // Determine if customer domain already has G Suite
    try {
      resellerService.customers().get(CUSTOMER_DOMAIN).execute();
      System.out.println("Customer already exists if call succeeds");
      System.exit(0);
    } catch (HttpResponseException e) {
        if (e.getStatusCode() == 404) {
          System.out.println("Domain available for G Suite creation");
        } else throw e;
    }

PHP

// Determine if customer domain already has G Suite
try {
  $response = $resellerService->customers->get($CUSTOMER_DOMAIN);
  exit("Customer already exists if call succeeds");
} catch(Google_Service_Exception $e) {
  if ($e->getErrors()[0]["reason"] == "notFound"){
    print("Domain available for G Suite creation\n");
  } else {
    throw $e;
  }
}

Ruby

# Determine if customer domain already has G Suite
begin
  reseller_service.get_customer(CUSTOMER_DOMAIN)
  abort('Customer already exists if call succeeds')
rescue Google::Apis::ClientError => ex
  if ex.status_code == 404
    puts 'Domain available for G Suite creation'
  else
    raise ex
  end
end	

Create a customer record in G Suite

You must create a customer record before you can create subscriptions for that customer. The API validates the customer address information, and returns an error if the validation fails. You should follow these guidelines:

  • The alternateEmail cannot be on the same domain as customerDomain.
  • The postalAddress.countryCode must be a two character ISO country code.

A customer creation example:

Python

# Create customer resource
response = reseller_service.customers().insert(body={
  'customerDomain': CUSTOMER_DOMAIN,
  'alternateEmail': 'marty.mcfly@gmail.com',
  'postalAddress': {
      'contactName': 'Marty McFly',
      'organizationName': 'Acme Corp',
      'postalCode': '10009',
      'countryCode': 'US',
    }
}).execute()
print response

Java

    // Create customer resource
    Address address = new Address()
      .setContactName("Marty McFly")
      .setOrganizationName("Acme Corp")
      .setCountryCode("US")
      .setPostalCode("10009");

    Customer customer = new Customer()
      .setCustomerDomain(CUSTOMER_DOMAIN)
      .setAlternateEmail("marty.mcfly@gmail.com")
      .setPostalAddress(address);

    Customer customerResponse = resellerService.customers()
      .insert(customer).execute();
    System.out.println("Created Customer:\n" + customerResponse);

PHP

// Create customer resource
$customer = new Google_Service_Reseller_Customer(array(
  "customerDomain" => $CUSTOMER_DOMAIN,
  "alternateEmail" => "marty.mcfly@gmail.com",
  "postalAddress" => array(
    "contactName" => "Marty McFly",
    "organizationName" => "Acme Corp",
    "countryCode"=> "US",
    "postalCode" => "10009"
  )
));
$response = $resellerService->customers->insert($customer);
print_r($response);

Ruby

# Create customer resource
customer = Google::Apis::ResellerV1::Customer.new(
  customer_domain: CUSTOMER_DOMAIN,
  alternate_email: 'marty.mcfly@gmail.com',
  postal_address: {
    contact_name: 'Marty McFly',
    organization_name: 'Acme Corp',
    country_code: 'US',
    postal_code: '10009'})

response = reseller_service.insert_customer(customer)
puts response.inspect

Step 4: Create the first admin user with the Admin SDK

Once a customer has been provisioned, it's important to create the first user so that the customer may access their new services. This user must be immediately upgraded to a domain super administrator, so that they can accept any applicable customer-centric Terms of Service.

Best practices and watchpoints:

  • If the newly created user call returns an HTTP 409, the username may already exist as a consumer Google account.
  • Passwords must be of adequate complexity (using the word 'password' is not acceptable) and must contain at least 8 characters.

A user creation example:

Python

# Create first admin user
response = directory_service.users().insert(
    body = {
        'primaryEmail': "marty.mcfly@" + CUSTOMER_DOMAIN,
        'name': {
            'givenName': 'Marty',
            'familyName': 'McFly',
        },
        'password': 'Timecircuit88'
    }
).execute()
print response

Java

    // Create first admin user
    String userEmail = "marty.mcfly@" + CUSTOMER_DOMAIN;

    UserName name = new UserName();
    name.setGivenName("Marty");
    name.setFamilyName("McFly");

    User user = new User();
    user.setPrimaryEmail(userEmail);
    user.setPassword("TimeCircuit88");
    user.setName(name);

    User userResponse = directoryService.users().insert(user).execute();
    System.out.println("Created User:\n" + userResponse);

PHP

// Create first admin user
$user = new Google_Service_Directory_User(array(
  "primaryEmail" => "marty.mcfly@" . $CUSTOMER_DOMAIN,
  "password" => "Timecircuit88",
  "name" => array(
    "givenName" =>"Marty",
    "familyName" => "McFly",
    "fullName" => "Marty McFly"
  )
));
$response = $directoryService->users->insert($user);
print_r($response);

Ruby

# Create first admin user
user = Google::Apis::AdminDirectoryV1::User.new(
  name: {
    given_name: 'Marty',
    family_name: 'McFly',
    full_name: 'Marty McFly'
  },
  password: 'Timecircuit88',
  primary_email: 'marty.mcfly@' + CUSTOMER_DOMAIN,
)

response = directory_service.insert_user(user)
puts response.inspect

Then, immediately upgrade the user to the super administrator role:

Python

# Promote user to admin status
response = directory_service.users().makeAdmin(
    userKey="marty.mcfly@" + CUSTOMER_DOMAIN,
    body={
        'status': True
    }
).execute()

Java

    // Promote user to admin status
    UserMakeAdmin admin = new UserMakeAdmin();
    admin.setStatus(true);

    directoryService.users().makeAdmin(userEmail, admin).execute();
    System.out.println("User promoted to Admin");

PHP

// Promote user to admin status
$makeAdmin = new Google_Service_Directory_UserMakeAdmin(array(
  "status" => TRUE
));
$directoryService->users->makeAdmin("marty.mcfly@" . $CUSTOMER_DOMAIN, $makeAdmin);

Ruby

# Promote user to admin status
admin_status = Google::Apis::AdminDirectoryV1::UserMakeAdmin.new(
  status: true
)

response = directory_service.make_user_admin('marty.mcfly@' + CUSTOMER_DOMAIN, admin_status)

Step 5: Create a G Suite subscription for a customer

To create a subscription, use the Subscriptions.Insert call. For more information on specific arguments and values, see Managing Subscriptions

A subscription creation example, using an ANNUAL_YEARLY_PAY subscription:

Python

# Create subscription resource
response = reseller_service.subscriptions().insert(
    customerId=CUSTOMER_DOMAIN,
    body={
      'customerId': CUSTOMER_DOMAIN,
      'skuId': 'Google-Apps-For-Business',
      'plan': {
        'planName': 'ANNUAL_MONTHLY_PAY',
      },
      'seats': {
          'numberOfSeats': 5,
      },
      'renewalSettings': { # only relevant for annual plans
          'renewalType': 'RENEW_CURRENT_USERS_MONTHLY_PAY'
      }
}).execute()
print response

Java

    // Create subscription resource
    Seats seats = new Seats()
      .setNumberOfSeats(5);

    Subscription.Plan plan = new Subscription.Plan()
      .setPlanName("ANNUAL_YEARLY_PAY");

    RenewalSettings renewalSettings = new RenewalSettings()
      .setRenewalType("RENEW_CURRENT_USERS_MONTHLY_PAY");

    Subscription subscription = new Subscription()
      .setCustomerId(CUSTOMER_DOMAIN)
      .setSeats(seats)
      .setPlan(plan)
      .setSkuId("Google-Apps-For-Business")
      .setRenewalSettings(renewalSettings);

    Subscription subscriptionResponse = resellerService.subscriptions()
      .insert(CUSTOMER_DOMAIN, subscription).execute();
    System.out.println("Created Subscription:\n" + subscriptionResponse);

PHP

// Create subscription resource
$subscription = new Google_Service_Reseller_Subscription(array(
  "customerId" => $CUSTOMER_DOMAIN,
  "skuId" => "Google-Apps-For-Business",
  "plan" => array(
    "planName" => "ANNUAL_MONTHLY_PAY"
  ),
  "seats" => array(
    "numberOfSeats" => "5"
  ),
  "renewalSettings" => array(
    "renewalType" => "RENEW_CURRENT_USERS_MONTHLY_PAY"
  )
));
$response = $resellerService->subscriptions->insert($CUSTOMER_DOMAIN, $subscription);
print_r($response);

Ruby

# Create subscription resource
subscription = Google::Apis::ResellerV1::Subscription.new(
  customer_id: CUSTOMER_DOMAIN,
  sku_id: 'Google-Apps-For-Business',
  plan: {
    plan_name: 'ANNUAL_MONTHLY_PAY'
  },
  seats: {
    number_of_seats: 5,
  },
  renewal_settings: {
    renewal_type: 'RENEW_CURRENT_USERS_MONTHLY_PAY'
  }
)

response = reseller_service.insert_subscription(CUSTOMER_DOMAIN, subscription)
puts response.inspect

Step 6: Verify domain and designate domain owners

Verify a customer's domain anytime after creating the admin user so that you can designate the admin user as the owner of the domain.

The Site Verification API webResource.insert() call will both verify a domain and assign to it the owners you specify in the owners[] parameter of the request body. This call returns an HTTP 200 code if successful.

If webResource.insert() can't verify the domain, it returns an HTTP 400-level error code. Retry the webResource.insert() call with a backoff delay until the domain is successfully verified.

The following example shows how to perform verification using a INET_DOMAIN type:

Python

# Verify domain and designate domain owners
response = verification_service.webResource().insert(
    verificationMethod='DNS_TXT',
    body={
        "site": {
            "type": 'INET_DOMAIN',
            "identifier": CUSTOMER_DOMAIN
        },
        'owners': [
            "marty.mcfly@" + CUSTOMER_DOMAIN
        ]
    }
).execute()
print response

Java

    // Verify domain and designate domain owners
    SiteVerificationWebResourceResource.Site verifySite =
          new SiteVerificationWebResourceResource.Site()
                .setIdentifier(CUSTOMER_DOMAIN)
                .setType("INET_DOMAIN");

    List<String> owners = Arrays.asList(userEmail);

    SiteVerificationWebResourceResource resource =
      new SiteVerificationWebResourceResource()
            .setSite(verifySite)
            .setOwners(owners);
    
    SiteVerificationWebResourceResource verifyResponse = 
      verificationService.webResource().insert("DNS_TXT", resource).execute();
    System.out.println("Site Verification Web Resource:\n" + verifyResponse);

PHP

// Verify domain and designate domain owners
$body = new Google_Service_SiteVerification_SiteVerificationWebResourceResource(array(
  "site" => array(
    "type" => "INET_DOMAIN",
    "identifier" => $CUSTOMER_DOMAIN,
  ),
  "owners" => ["marty.mcfly@" . $CUSTOMER_DOMAIN]
));

$response = $verificationService->webResource->insert("DNS_TXT", $body);
print_r($response);

Ruby

# Verify domain and designate domain owners
webResource = Google::Apis::SiteVerificationV1::SiteVerificationWebResourceResource.new(
  site: {
    type: 'INET_DOMAIN',
    identifier: CUSTOMER_DOMAIN
  },
  owners: ['marty.mcfly@' + CUSTOMER_DOMAIN]
)

response = verification_service.insert_web_resource('DNS_TXT', webResource)
puts response.inspect

Put it all together

Python

import sys
from oauth2client.service_account import ServiceAccountCredentials
from apiclient.discovery import build
from apiclient.http import httplib2
from apiclient.http import HttpError

############## REPLACE WITH YOUR OWN VALUES ####################
JSON_PRIVATE_KEY_FILE = 'path/to/json_key_file.json'
RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com'
CUSTOMER_DOMAIN = 'customerdomain.com'
################################################################

# Full List of scopes:
# https://developers.google.com/identity/protocols/googlescopes
OAUTH2_SCOPES = [
    'https://www.googleapis.com/auth/apps.order',
    'https://www.googleapis.com/auth/siteverification',
    'https://www.googleapis.com/auth/admin.directory.user',
]

credentials = ServiceAccountCredentials.from_json_keyfile_name(
                JSON_PRIVATE_KEY_FILE,
                OAUTH2_SCOPES
              ).create_delegated(RESELLER_ADMIN_USER)

reseller_service = build(serviceName='reseller',
                         version='v1',
                         credentials=credentials,
                         http=httplib2.Http())

directory_service = build(serviceName='admin',
                          version='directory_v1',
                          credentials=credentials,
                          http=httplib2.Http())

verification_service = build(serviceName='siteVerification',
                             version='v1',
                             credentials=credentials,
                             http=httplib2.Http())


# Retrieve the site verification token and place it according to:
# https://developers.google.com/site-verification/v1/getting_started#tokens
response = verification_service.webResource().getToken(
    body={
        'site': {
            'type': 'INET_DOMAIN',
            'identifier': CUSTOMER_DOMAIN
        },
        'verificationMethod': 'DNS_TXT'
    }
).execute()
print response

# Determine if customer domain already has G Suite
try:
  response = reseller_service.customers().get(
    customerId=CUSTOMER_DOMAIN).execute()
  print "Customer already exists if call succeeds"
  sys.exit()
except HttpError as error:
  if int(error.resp['status']) == 404:
    print "Domain available for G Suite creation"
  else:
    raise

# Create customer resource
response = reseller_service.customers().insert(body={
  'customerDomain': CUSTOMER_DOMAIN,
  'alternateEmail': 'marty.mcfly@gmail.com',
  'postalAddress': {
      'contactName': 'Marty McFly',
      'organizationName': 'Acme Corp',
      'postalCode': '10009',
      'countryCode': 'US',
    }
}).execute()
print response

# Create first admin user
response = directory_service.users().insert(
    body = {
        'primaryEmail': "marty.mcfly@" + CUSTOMER_DOMAIN,
        'name': {
            'givenName': 'Marty',
            'familyName': 'McFly',
        },
        'password': 'Timecircuit88'
    }
).execute()
print response

# Promote user to admin status
response = directory_service.users().makeAdmin(
    userKey="marty.mcfly@" + CUSTOMER_DOMAIN,
    body={
        'status': True
    }
).execute()

# Create subscription resource
response = reseller_service.subscriptions().insert(
    customerId=CUSTOMER_DOMAIN,
    body={
      'customerId': CUSTOMER_DOMAIN,
      'skuId': 'Google-Apps-For-Business',
      'plan': {
        'planName': 'ANNUAL_MONTHLY_PAY',
      },
      'seats': {
          'numberOfSeats': 5,
      },
      'renewalSettings': { # only relevant for annual plans
          'renewalType': 'RENEW_CURRENT_USERS_MONTHLY_PAY'
      }
}).execute()
print response

# Verify domain and designate domain owners
response = verification_service.webResource().insert(
    verificationMethod='DNS_TXT',
    body={
        "site": {
            "type": 'INET_DOMAIN',
            "identifier": CUSTOMER_DOMAIN
        },
        'owners': [
            "marty.mcfly@" + CUSTOMER_DOMAIN
        ]
    }
).execute()
print response

Java

// OAuth2 and HTTP
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpResponseException;
// Reseller API
import com.google.api.services.reseller.*;
import com.google.api.services.reseller.model.*;
// Directory API
import com.google.api.services.admin.directory.*;
import com.google.api.services.admin.directory.model.User;
import com.google.api.services.admin.directory.model.UserName;
import com.google.api.services.admin.directory.model.UserMakeAdmin;
// Site Verification API
import com.google.api.services.siteVerification.*;
import com.google.api.services.siteVerification.model.*;
// Java library imports
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.io.FileNotFoundException;
import java.util.Arrays;
import java.util.List;

public class CodelabExample {
  // Full List of scopes:
  // https://developers.google.com/identity/protocols/googlescopes
  private static final List<String> OAUTH2_SCOPES = Arrays.asList(
    ResellerScopes.APPS_ORDER,
    SiteVerificationScopes.SITEVERIFICATION,
    DirectoryScopes.ADMIN_DIRECTORY_USER
  );

  /***************** REPLACE WITH YOUR OWN VALUES ********************************/
  public static final String JSON_PRIVATE_KEY_FILE = "jsonprivatekey.json";
  public static final String RESELLER_ADMIN_USER = "admin@yourresellerdomain.com";
  public static final String CUSTOMER_DOMAIN = "customerdomain.com";
  /*******************************************************************************/

  public static void main(String[] args)
      throws IOException, GeneralSecurityException, FileNotFoundException {
    // Instantiate services with authenticated credentials
    GoogleCredential jsonCredentials = GoogleCredential
      .fromStream(new FileInputStream(JSON_PRIVATE_KEY_FILE));
    GoogleCredential credentials = new GoogleCredential.Builder()
      .setTransport(GoogleNetHttpTransport.newTrustedTransport())
      .setJsonFactory(JacksonFactory.getDefaultInstance())
      .setServiceAccountScopes(OAUTH2_SCOPES)
      .setServiceAccountUser(RESELLER_ADMIN_USER)
      .setServiceAccountPrivateKey(jsonCredentials.getServiceAccountPrivateKey())
      .setServiceAccountId(jsonCredentials.getServiceAccountId())
      .build();

    Reseller resellerService = new Reseller.Builder(
        credentials.getTransport(),
        credentials.getJsonFactory(),
        credentials).setApplicationName("G Suite Creator").build();

    Directory directoryService = new Directory.Builder(
        credentials.getTransport(),
        credentials.getJsonFactory(),
        credentials).setApplicationName("G Suite Creator").build();

    SiteVerification verificationService = new SiteVerification.Builder(
        credentials.getTransport(),
        credentials.getJsonFactory(),
        credentials).setApplicationName("G Suite Creator").build();

    // Retrieve the site verification token and place it according to:
    // https://developers.google.com/site-verification/v1/getting_started#tokens
    SiteVerificationWebResourceGettokenRequest.Site getTokenSite =
        new SiteVerificationWebResourceGettokenRequest.Site()
            .setType("INET_DOMAIN")
            .setIdentifier(CUSTOMER_DOMAIN);

    SiteVerificationWebResourceGettokenRequest request =
        new SiteVerificationWebResourceGettokenRequest()
            .setVerificationMethod("DNS_TXT")
            .setSite(getTokenSite);

    SiteVerificationWebResourceGettokenResponse getTokenResponse =
        verificationService.webResource().getToken(request).execute();
    System.out.println("Site Verification Token: " + getTokenResponse.getToken());


    // Determine if customer domain already has G Suite
    try {
      resellerService.customers().get(CUSTOMER_DOMAIN).execute();
      System.out.println("Customer already exists if call succeeds");
      System.exit(0);
    } catch (HttpResponseException e) {
        if (e.getStatusCode() == 404) {
          System.out.println("Domain available for G Suite creation");
        } else throw e;
    }

    // Create customer resource
    Address address = new Address()
      .setContactName("Marty McFly")
      .setOrganizationName("Acme Corp")
      .setCountryCode("US")
      .setPostalCode("10009");

    Customer customer = new Customer()
      .setCustomerDomain(CUSTOMER_DOMAIN)
      .setAlternateEmail("marty.mcfly@gmail.com")
      .setPostalAddress(address);

    Customer customerResponse = resellerService.customers()
      .insert(customer).execute();
    System.out.println("Created Customer:\n" + customerResponse);

    // Create first admin user
    String userEmail = "marty.mcfly@" + CUSTOMER_DOMAIN;

    UserName name = new UserName();
    name.setGivenName("Marty");
    name.setFamilyName("McFly");

    User user = new User();
    user.setPrimaryEmail(userEmail);
    user.setPassword("TimeCircuit88");
    user.setName(name);

    User userResponse = directoryService.users().insert(user).execute();
    System.out.println("Created User:\n" + userResponse);

    // Promote user to admin status
    UserMakeAdmin admin = new UserMakeAdmin();
    admin.setStatus(true);

    directoryService.users().makeAdmin(userEmail, admin).execute();
    System.out.println("User promoted to Admin");

    // Create subscription resource
    Seats seats = new Seats()
      .setNumberOfSeats(5);

    Subscription.Plan plan = new Subscription.Plan()
      .setPlanName("ANNUAL_YEARLY_PAY");

    RenewalSettings renewalSettings = new RenewalSettings()
      .setRenewalType("RENEW_CURRENT_USERS_MONTHLY_PAY");

    Subscription subscription = new Subscription()
      .setCustomerId(CUSTOMER_DOMAIN)
      .setSeats(seats)
      .setPlan(plan)
      .setSkuId("Google-Apps-For-Business")
      .setRenewalSettings(renewalSettings);

    Subscription subscriptionResponse = resellerService.subscriptions()
      .insert(CUSTOMER_DOMAIN, subscription).execute();
    System.out.println("Created Subscription:\n" + subscriptionResponse);

    // Verify domain and designate domain owners
    SiteVerificationWebResourceResource.Site verifySite =
          new SiteVerificationWebResourceResource.Site()
                .setIdentifier(CUSTOMER_DOMAIN)
                .setType("INET_DOMAIN");

    List owners = Arrays.asList(userEmail);

    SiteVerificationWebResourceResource resource =
      new SiteVerificationWebResourceResource()
            .setSite(verifySite)
            .setOwners(owners);
    
    SiteVerificationWebResourceResource verifyResponse = 
      verificationService.webResource().insert("DNS_TXT", resource).execute();
    System.out.println("Site Verification Web Resource:\n" + verifyResponse);
  }
}

PHP

<?php
// https://developers.google.com/api-client-library/php/
require_once "vendor/autoload.php";

// Full List of scopes:
// https://developers.google.com/identity/protocols/googlescopes
$OAUTH2_SCOPES = array(
  Google_Service_Reseller::APPS_ORDER,
  Google_Service_SiteVerification::SITEVERIFICATION,
  Google_Service_Directory::ADMIN_DIRECTORY_USER,
);

######### REPLACE WITH YOUR OWN VALUES ###############
$JSON_PRIVATE_KEY_FILE = "path/to/json_key_file.json";
$RESELLER_ADMIN_USER = "admin@yourresellerdomain.com";
$CUSTOMER_DOMAIN = "customerdomain.com";
######################################################

$client = new Google_Client();
$client->setAuthConfig($JSON_PRIVATE_KEY_FILE);
$client->setSubject($RESELLER_ADMIN_USER);
$client->setScopes($OAUTH2_SCOPES);

$resellerService = new Google_Service_Reseller($client);
$directoryService = new Google_Service_Directory($client);
$verificationService = new Google_Service_SiteVerification($client);

// Retrieve the site verification token and place it according to:
// https://developers.google.com/site-verification/v1/getting_started#tokens
$body = new Google_Service_SiteVerification_SiteVerificationWebResourceGettokenRequest(array(
  "verificationMethod" => "DNS_TXT",
  "site" => array(
    "type" => "INET_DOMAIN",
    "identifier" => $CUSTOMER_DOMAIN
  )
));
$response = $verificationService->webResource->getToken($body);
print_r($response);

// Determine if customer domain already has G Suite
try {
  $response = $resellerService->customers->get($CUSTOMER_DOMAIN);
  exit("Customer already exists if call succeeds");
} catch(Google_Service_Exception $e) {
  if ($e->getErrors()[0]["reason"] == "notFound"){
    print("Domain available for G Suite creation\n");
  } else {
    throw $e;
  }
}

// Create customer resource
$customer = new Google_Service_Reseller_Customer(array(
  "customerDomain" => $CUSTOMER_DOMAIN,
  "alternateEmail" => "marty.mcfly@gmail.com",
  "postalAddress" => array(
    "contactName" => "Marty McFly",
    "organizationName" => "Acme Corp",
    "countryCode"=> "US",
    "postalCode" => "10009"
  )
));
$response = $resellerService->customers->insert($customer);
print_r($response);

// Create first admin user
$user = new Google_Service_Directory_User(array(
  "primaryEmail" => "marty.mcfly@" . $CUSTOMER_DOMAIN,
  "password" => "Timecircuit88",
  "name" => array(
    "givenName" =>"Marty",
    "familyName" => "McFly",
    "fullName" => "Marty McFly"
  )
));
$response = $directoryService->users->insert($user);
print_r($response);

// Promote user to admin status
$makeAdmin = new Google_Service_Directory_UserMakeAdmin(array(
  "status" => TRUE
));
$directoryService->users->makeAdmin("marty.mcfly@" . $CUSTOMER_DOMAIN, $makeAdmin);

// Create subscription resource
$subscription = new Google_Service_Reseller_Subscription(array(
  "customerId" => $CUSTOMER_DOMAIN,
  "skuId" => "Google-Apps-For-Business",
  "plan" => array(
    "planName" => "ANNUAL_MONTHLY_PAY"
  ),
  "seats" => array(
    "numberOfSeats" => "5"
  ),
  "renewalSettings" => array(
    "renewalType" => "RENEW_CURRENT_USERS_MONTHLY_PAY"
  )
));
$response = $resellerService->subscriptions->insert($CUSTOMER_DOMAIN, $subscription);
print_r($response);

// Verify domain and designate domain owners
$body = new Google_Service_SiteVerification_SiteVerificationWebResourceResource(array(
  "site" => array(
    "type" => "INET_DOMAIN",
    "identifier" => $CUSTOMER_DOMAIN,
  ),
  "owners" => ["marty.mcfly@" . $CUSTOMER_DOMAIN]
));

$response = $verificationService->webResource->insert("DNS_TXT", $body);
print_r($response);
?>

Ruby

require 'googleauth'
require 'google/apis/reseller_v1'
require 'google/apis/site_verification_v1'
require 'google/apis/admin_directory_v1'

# Full List of scopes:
# https://developers.google.com/identity/protocols/googlescopes
OAUTH2_SCOPES = [
  'https://www.googleapis.com/auth/apps.order',
  'https://www.googleapis.com/auth/admin.directory.user',
  'https://www.googleapis.com/auth/siteverification',
]

####### REPLACE WITH YOUR OWN VALUES ###############
JSON_PRIVATE_KEY_FILE = 'path/to/json_key_file.json'
RESELLER_ADMIN_USER = 'admin@yourresellerdomain.com'
CUSTOMER_DOMAIN = 'customerdomain.com'
####################################################

credentials = Google::Auth::ServiceAccountCredentials.make_creds(
  json_key_io: File.open(JSON_PRIVATE_KEY_FILE),
  scope: OAUTH2_SCOPES)
credentials.sub = RESELLER_ADMIN_USER

Google::Apis::RequestOptions.default.authorization = credentials

reseller_service = Google::Apis::ResellerV1::ResellerService.new
directory_service = Google::Apis::AdminDirectoryV1::DirectoryService.new
verification_service = Google::Apis::SiteVerificationV1::SiteVerificationService.new

# Retrieve the site verification token and place it according to:
# https://developers.google.com/site-verification/v1/getting_started#tokens
request = Google::Apis::SiteVerificationV1::GetWebResourceTokenRequest.new(
  site: {
    type: 'INET_DOMAIN',
    identifier: CUSTOMER_DOMAIN
  },
  verification_method: 'DNS_TXT'
)

response = verification_service.get_web_resource_token(request)
puts response.inspect

# Determine if customer domain already has G Suite
begin
  reseller_service.get_customer(CUSTOMER_DOMAIN)
  abort('Customer already exists if call succeeds')
rescue Google::Apis::ClientError => ex
  if ex.status_code == 404
    puts 'Domain available for G Suite creation'
  else
    raise ex
  end
end	

# Create customer resource
customer = Google::Apis::ResellerV1::Customer.new(
  customer_domain: CUSTOMER_DOMAIN,
  alternate_email: 'marty.mcfly@gmail.com',
  postal_address: {
    contact_name: 'Marty McFly',
    organization_name: 'Acme Corp',
    country_code: 'US',
    postal_code: '10009'})

response = reseller_service.insert_customer(customer)
puts response.inspect

# Create first admin user
user = Google::Apis::AdminDirectoryV1::User.new(
  name: {
    given_name: 'Marty',
    family_name: 'McFly',
    full_name: 'Marty McFly'
  },
  password: 'Timecircuit88',
  primary_email: 'marty.mcfly@' + CUSTOMER_DOMAIN,
)

response = directory_service.insert_user(user)
puts response.inspect

# Promote user to admin status
admin_status = Google::Apis::AdminDirectoryV1::UserMakeAdmin.new(
  status: true
)

response = directory_service.make_user_admin('marty.mcfly@' + CUSTOMER_DOMAIN, admin_status)

# Create subscription resource
subscription = Google::Apis::ResellerV1::Subscription.new(
  customer_id: CUSTOMER_DOMAIN,
  sku_id: 'Google-Apps-For-Business',
  plan: {
    plan_name: 'ANNUAL_MONTHLY_PAY'
  },
  seats: {
    number_of_seats: 5,
  },
  renewal_settings: {
    renewal_type: 'RENEW_CURRENT_USERS_MONTHLY_PAY'
  }
)

response = reseller_service.insert_subscription(CUSTOMER_DOMAIN, subscription)
puts response.inspect

# Verify domain and designate domain owners
webResource = Google::Apis::SiteVerificationV1::SiteVerificationWebResourceResource.new(
  site: {
    type: 'INET_DOMAIN',
    identifier: CUSTOMER_DOMAIN
  },
  owners: ['marty.mcfly@' + CUSTOMER_DOMAIN]
)

response = verification_service.insert_web_resource('DNS_TXT', webResource)
puts response.inspect

Send feedback about...

G Suite Reseller API
G Suite Reseller API