title: Google API for getting maximum number of licenses in a Google Apps domain
body: <p>I have a Google Apps Script function used for setting up accounts for new employees in our Google Apps domain. </p>
  
  <p>The first thing it does is makes calls to the <a href="https://developers.google.com/admin-sdk/admin-settings/#managing_general_domain_settings" rel="nofollow noreferrer">Google Admin Settings API</a> and retrieves the <strong>currentNumberOfUsers</strong> and <strong>maximumNumberOfUsers</strong>, so it can see if there are available seats (otherwise a subsequent step where the user is created using the <a href="https://developers.google.com/admin-sdk/directory/v1/reference/users/insert" rel="nofollow noreferrer">Admin SDK Directory API</a> would fail). </p>
  
  <p>It's been working fine until recently when our domain had to migrate from Postini to Google Vault for email archiving.</p>
  
  <p><strong><em>Before</em></strong> the migration, when creating a Google Apps user using the <a href="https://developers.google.com/admin-sdk/directory/v1/reference/users/insert" rel="nofollow noreferrer">Admin SDK Directory API</a>, it would increment the <strong>currentNumberOfUsers</strong> by 1 and the new user account user would automatically have access to all Google Apps services. </p>
  
  <p><strong><em>Now after</em></strong> the migration, when creating a Google Apps user, they aren't automatically assigned a "license," so I modified my script to use the <a href="https://developers.google.com/admin-sdk/licensing/v1/reference/licenseAssignments/insert" rel="nofollow noreferrer">Enterprise License Manager API</a> and now it assigns a <code>"Google-Apps-For-Business"</code> license. That works fine.</p>
  
  <p>However, the <strong><em>currentNumberOfUsers</em></strong> is now different from the <em>number of assigned licenses</em>, and <code>"Google-Apps-For-Business"</code> is only <a href="https://developers.google.com/admin-sdk/licensing/v1/how-tos/products" rel="nofollow noreferrer">one of several different types of licenses available</a>.</p>
  
  <p>I can get the current number of <strong><em>assigned</em></strong> <code>"Google-Apps-For-Business"</code> licenses by running this: </p>
  
  <p><div class="snippet" data-lang="js" data-hide="false" data-console="false" data-babel="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var currentXml = AdminLicenseManager.LicenseAssignments.listForProductAndSku('Google-Apps', 'Google-Apps-For-Business', 'domain.com', {maxResults: 1000});
      
  var current = currentXml.items.toString().match(/\/sku\/Google-Apps-For-Business\/user\//g).length;</code></pre>
  </div>
  </div>
  </p>
  
  <p>But the number that produces is different from <strong><em>currentNumberOfUsers</em></strong>. </p>
  
  <p>All I really need to do now is get the <strong><em>maximum</em></strong> number of owned <code>"Google-Apps-For-Business"</code> licenses so the new employee setup script can determine whether there are any available.  </p>
  
  <p>I checked the API Reference documentation for the following APIs but...</p>
  
  <p><a href="https://developers.google.com/admin-sdk/licensing/v1/reference/licenseAssignments/insert" rel="nofollow noreferrer">Enterprise License Manager API</a> → Doesn't have a method for getting the maximum or available number of licenses.</p>
  
  <p><a href="https://developers.google.com/admin-sdk/admin-settings/#managing_general_domain_settings" rel="nofollow noreferrer">Google Admin Settings API</a> → Doesn't deal with licenses, only "users."</p>
  
  <p><a href="https://developers.google.com/admin-sdk/directory/v1/reference/users#resource" rel="nofollow noreferrer">Admin SDK Directory API User resource</a> → Doesn't deal with licenses.</p>
  
  <p><a href="https://developers.google.com/admin-sdk/reseller/v1/reference/subscriptions#resource" rel="nofollow noreferrer">Google Apps Reseller API</a> → This API seems to have what I need, but <a href="https://developers.google.com/admin-sdk/reseller/v1/how-tos/prerequisites" rel="nofollow noreferrer">it's only for Reseller accounts</a>. </p>
  
  <p>I know I can program my new employee setup script to just have a try/catch seeing if it would be able to create the user and assign the license, and end the script execution gracefully if it can't, but that doesn't seem efficient. </p>
  
  <p>Also, part of the old script was that if there were less than X seats available, it would email me a heads-up to order more. I can program a loop that attempts to repeatedly create dummy users and assign them licenses and count the number of times it can do that before it fails, then delete all the dummy users, but, once again, that's not efficient at all.  </p>
  
  <p>Any ideas?</p>
  
  <p><strong>Update 3/11/2020</strong>: Since the Admin Settings API had shut down a few years ago I've been using the Enterprise License Manager API to get the current number of used licenses, like this: </p>
  
  <pre><code>function getCurrentNumberOfUsedGoogleLicenses(skuId) {
  
    var success = false, error = null, count = 0;
  
    var adminEmail = 'admin@domain.com';
    var gSuiteDomain = adminEmail.split('@')[1];
  
    // for more information on the domain-wide delegation:
    // https://developers.google.com/identity/protocols/OAuth2ServiceAccount#delegatingauthority
    // the getDomainWideDelegationService() function uses this: 
    // https://github.com/gsuitedevs/apps-script-oauth2
    var service = getDomainWideDelegationService('EnterpriseLicenseManager: ', 'https://www.googleapis.com/auth/apps.licensing', adminEmail);
  
    if (skuId == 'Google-Apps-Unlimited') var productId = 'Google-Apps';
    else                                  return { success: success, error: "Unsupported skuId", count: count };
  
    var requestBody                = {};
    requestBody.headers            = {'Authorization': 'Bearer ' + service.getAccessToken()};
    requestBody.method             = "GET";
    requestBody.muteHttpExceptions = false;
  
    var data, pageToken, pageTokenString;
  
    var maxAttempts     = 5;
    var currentAttempts = 0;
    var pauseBetweenAttemptsSeconds = 3;
  
    loopThroughPages:
    do {
  
      if (typeof pageToken === 'undefined') pageTokenString = "";
      else                                  pageTokenString = "&amp;pageToken=" + encodeURIComponent(pageToken);
  
      var url = 'https://www.googleapis.com/apps/licensing/v1/product/' + productId + '/sku/' + skuId + '/users?maxResults=1000&amp;customerId=' + gSuiteDomain + pageTokenString;
  
      try {
  
        currentAttempts++;
  
        var response = UrlFetchApp.fetch(url, requestBody);
  
        var result = JSON.parse(response.getContentText());
  
        if (result.items) {
  
          var licenseAssignments = result.items;
          var licenseAssignmentsString = '';
  
          for (var i = 0; i &lt; licenseAssignments.length; i++) {
  
            licenseAssignmentsString += JSON.stringify(licenseAssignments[i]);
  
          }
  
          if (skuId == 'Google-Apps-Unlimited') count += licenseAssignmentsString.match(/\/sku\/Google-Apps-Unlimited\/user\//g).length;
  
          currentAttempts = 0; // reset currentAttempts before the next page
  
        }
  
      } catch(e) {
  
        error = "Error: " + e.message;
  
        if (currentAttempts &gt;= maxAttempts) {
  
          error = 'Exceeded ' + maxAttempts + ' attempts to get license count: ' + error;
  
          break loopThroughPages;
  
        }
  
      } // end of try catch
  
      if (result) pageToken = result.nextPageToken;
  
    } while (pageToken);
  
    if (!error) success = true;
  
    return { success: success, error: error, count: count };
  
  }
  </code></pre>
  
  <p>However, there still does not appear to be a way to get the maximum number available to the domain using this API.</p>