X

API How-To

Organization Administration

Introduction

In order to scale an enterprise deployment, developers typically automate the creation of accounts (users) and groups. nVoq's organizational hierarchy allows for the creation of organization structures that reduce administrative overhead by allowing the application of certain operations to groups of accounts. For example, if a hospital was located on Squeezepenny Lane, the custom vocabulary word "Squeezepenny" could be added once and applied to all the accounts within the hospital's organization hierarchy. It then becomes part of those accounts' vocabularies through one administrative operation. This prevents errors from duplicated data spread across an organization and simplifies troubleshooting.

The nVoq API allows for organization creation (company, division, and group) within each tenant. Accounts can be assigned to groups for performing dictation and matching operations. Administrative access can be granted at each level in the organization hierarchy as appropriate. Subscription and billing options can be managed via the API as well.

This How-To covers the creation and management of organizations within your tenant's organizational hierarchy.

Before You Begin

Background Info

If you are not already familiar with nVoq's organization hierarchy functionality, please check out the Organizations page on our support site that walks you through how organizations are structured, administered, and used to organize accounts and control administrative privileges. The hierarchy has a fixed structure and is illustrated in the diagram below.
Organizational Hierarchy

API User Account

If your organization has not already been in contact with our Sales team, please complete this short form on the Developer Registration Page and we will reach out to you regarding a user account and development with our APIs.

Once you have an account, you must change your password before the account can be used for API calls.

External Dependecies

Most platforms do not include a JSON implementation. So, you will need to download the appropriate third party implementation from one of these locations:

Start your IDE

The nVoq API is a RESTful Web Services and WebSocket API and therefore does not constrain you to any specific platform or programming language. We provide sample code below for shell scripting (bash), C#, Java, and JavaScript. Follow along and run this code in your environment. But, if you prefer C++, Go, or some other language, that's great! Just adapt the code below to your language's web services functionality and you should be good to go.

Let's Go!

Choose your programming language...

Step 1: Retrieve Full Hierarchy

The first thing to do when working with your organizational hierarchy is to retrieve the hierarchy as it exists. A simple web services call returns the organization hierarchy as a JSON document. The member variables and helper methods are available in the full sample source code at the bottom of this document.

#!/bin/bash
#TBD

  
import java.io.*;
import org.json.simple.*;
import org.json.simple.parser.*;
import java.net.*;
import java.util.*;

public class Program {
   // Your username
   private String username = "yourUsername";
   // Your password
   private String password = "yourPassword";
   // Server URL
   private String baseUrl = "https://test.nvoq.com";
   // Topmost Organization in the hierarchy accessible to API user
   private Organization myTopLevelOrg = null;
   // Enterprise Pricing Plan Reference
   private Plan myEnterprisePlan = null;
   // the Location Header returned from the last Organization Operation
   private String lastLocation = null;
   
   /*
    *  Retrieve the organizations visible to this user.
    */
   private void getOrganizations() {
      String url = baseUrl + "/SCVmcServices/rest/organizations";
      try {

         StringBuffer sb = httpHelper("GET", url, null);
         myTopLevelOrg = new Organization(sb.toString());

      } catch (Exception e) {
         System.out.println(e.toString());
      }
      return;
   }

   /*
    * Helper Method to make a HTTP request and return a StringBuffer with
    * the HTTP response body.  The contents of the Location HTTP header field
    * are also stored in the lastLocation variable for future reference.
    */
   private StringBuffer httpHelper(String operation, String url, String content) {
      StringBuffer sbIn = null;
      lastLocation = null;
      try {

         URL myurl = new URL(url);
         HttpURLConnection con = (HttpURLConnection) myurl.openConnection();
         con.setDoOutput(true);
         String credentials = username + ":" + password;
         String basicAuth = "Basic " + new String(Base64.getEncoder().encode(credentials.getBytes()));
         con.setRequestProperty("Authorization", basicAuth);
         con.setRequestMethod(operation);

         if (operation.equalsIgnoreCase("POST")) {
            con.setRequestProperty("Content-Type", "application/json");
            DataOutputStream wr = new DataOutputStream(con.getOutputStream());
            wr.write(content.getBytes());
            wr.flush();
         }
         lastLocation = con.getHeaderField("Location");
         BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
         sbIn = new StringBuffer();
         String inputLine;
         while ((inputLine = in.readLine()) != null)
            sbIn.append(inputLine);
         in.close();
         return sbIn;

      } catch (Exception e) {
         System.out.println(e.toString());
         if (sbIn != null) {
            System.out.println(sbIn.toString());
         }
      }
      return null;
   }
   
   /*
    * Inner class to represent an organization in the hierarchy.
    */
   class Organization {
      String myName;
      String myLevel;
      String myId;
      //many more properties actually available...
      
      //child organizations (it's a hierarchy)
      ArrayList<Organization> myChildren = new ArrayList<Organization>();

      public Organization(String aName, String aLevel, String aId) {
         myName = aName;
         myLevel = aLevel;
         myId = aId;
      }

      /*
       * Creates an organization object from a JSON string
       */
      public Organization(String aJsonString) {

         try {
            JSONParser jsonParser = new JSONParser();
            Object obj = jsonParser.parse(aJsonString.toString());
            JSONObject jso = (JSONObject) obj;
            myName = jso.get("name").toString();
            myLevel = jso.get("level").toString();
            myId = jso.get("identifier").toString();
            JSONArray childArray = (JSONArray) jso.get("children");
            childArray.forEach((child) -> this.addChild(child.toString()));
         } catch (Exception e) {
            System.out.println("Something went wrong: " + e.toString());
         }
      }
      
      /*
       * Add a child org to this organization
       */
      public void addChild(String aChildString) {
         JSONParser jsonParser = new JSONParser();
         try {
            Object obj = jsonParser.parse(aChildString);
            JSONObject jso = (JSONObject) obj;
            Organization newChildOrg = new Organization(jso.toString());
            myChildren.add(newChildOrg);
         } catch (Exception e) {
            System.out.println("something went wrong: " + e.toString());
         }
      }
      
      /*
       * Print out our full hierarchy including orgs, accounts, and plans.
       */
      public void print(int level) {
         StringBuffer leadIn = new StringBuffer();
         for (int x = 0; x < level; x++) {
            leadIn.append("--");
         }
         StringBuffer sb = new StringBuffer();
         sb.append(leadIn);
         sb.append("+organization: ");
         sb.append(myName);
         sb.append(" [" + myLevel + "]");
         System.out.println(sb);

         myChildren.forEach(c -> c.print(level + 1));
      }
   }   

 

<script>
//TBD
</script>
  
  

  
using Newtonsoft.Json;
using System;
using System.IO;
using System.Net;
using System.Text;

namespace nVoqHttpApiCSharp
{
    class Program
    {
        /**** Begin configuration settings ****/
        // Your username
        const string Username = "yourUsername";
        // Your password
        const string Password = "yourPassword";
        // Server URL
        const string BaseUrl = "https://test.nvoq.com";
        //last Location header returned from the server
        static string lastLocation = null;
        //reference to the top level org in the hierarchy
        static Organization topLevelOrg = null;

        public static NullValueHandling NullValueHandling { get; set; }
        /**** End configuration settings   ****/
 
        /*
         * Get the top level organization in the hierarchy
         */
         private static Organization getOrgs()
        {
            string url = BaseUrl + "/SCVmcServices/rest/organizations";
            string orgHierarchy = httpHelper("GET", url, null);
            topLevelOrg = JsonConvert.DeserializeObject<Organization>(orgHierarchy);
            return topLevelOrg;
        }
        
        /*
         * Internal class to represent organizations
         */
        public class Organization
        {
            public string name;
            public string level;
            public bool enabled;
            public string identifier;
            public Organization[] children = new Organization[0];
            //don't serialize children if there aren't any
            public bool ShouldSerializechildren()
            {
                if (children.Length == 0){
                    return false;
                }
                return true;
            }

            public Organization()
            {

            }
            public void print(int indent)
            {
                String leadIn = "";
                for (int x = 0; x < indent; x++)
                {
                    leadIn = leadIn + "--";
                }
                String sb = "";
                sb = sb + leadIn;
                sb = sb + "+organization: ";
                sb = sb + name;
                sb = sb + " [" + level + "]";
                Console.WriteLine(sb);

                foreach(Organization org in children)
                {
                    org.print(indent + 1);
                }

            }

        }        
        
        /*
         * The following methods are helpers for dealing with the
         * HTTP API.
         */
        private static string httpHelper(string operation, string url, string content)
        {
            HttpWebRequest request = BuildRequest(operation, url);
            if (operation.Equals("POST"))
            {
                request.ContentType =  "application/json";
                byte[] bytes = Encoding.ASCII.GetBytes(content);
                using (Stream requestStream = request.GetRequestStream())
                    requestStream.Write(bytes, 0, bytes.Length);
            }
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            string responseString = ReadStreamAsUtf8String(response.GetResponseStream());
            //Console.WriteLine(responseString);
            lastLocation = response.GetResponseHeader("Location");
            return responseString;
        }
        private static HttpWebRequest BuildRequest(string method, string url)
        {
            HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create(url);
            httpRequest.Method = method;
            httpRequest.Headers.Add("Authorization", "Basic "
                + Convert.ToBase64String(Encoding.ASCII.GetBytes(Username + ":" + Password)));
            return httpRequest;
        }

        private static byte[] ReadStreamAsBytes(Stream s)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                byte[] buf = new byte[8192];
                int len;
                while ((len = s.Read(buf, 0, buf.Length)) != 0)
                    ms.Write(buf, 0, len);
                return ms.ToArray();
            }
        }

        private static string ReadStreamAsUtf8String(Stream s)
        {
            return Encoding.UTF8.GetString(ReadStreamAsBytes(s));
        }
        //...
  
  

Step 2: Create an Organization

Once you have a starting point, you can add organizations as children of other organizations. As a developer you will typically have access to the entire hierarchy, beginning with the tenant organization at the top. As a reminder, the hierarchy is four levels deep.

#TBD

  
   /*
    * Creates an org under the specified parent organization, with the appropriate
    * level.
    */
   private Organization createOrganization(String organizationName, String parentId) {

      String url = baseUrl + "/SCVmcServices/rest/organizations/" + parentId + "/children";

      //JSON representation of new organization
      StringBuffer sb = new StringBuffer();
      sb.append("{\"name\": \"" + organizationName + "\",\n");
      sb.append("\"enabled\":true }");
      String newOrgDefinition = sb.toString();

      //post to create the new organization
      try {
         StringBuffer sbOrg = httpHelper("POST", url, newOrgDefinition);
         //returns JSON representation of new org, including unique ID
         Organization org = new Organization(sbOrg.toString());
         return org;
      } catch (Exception e) {
         System.out.println(e.toString());
      }
      return null;
   }
  
<script>
     //TBD
   </script>
  

  
        /*
         * Create a new organizaiton
         */
        private static Organization createOrg(String aName, String aParentId)
        {

            String url = BaseUrl + "/SCVmcServices/rest/organizations/" + aParentId + "/children";
            Console.WriteLine(url);
            Organization newOrg = new Organization();
            newOrg.name = aName;
            newOrg.enabled = true;
            //create the object JSON but don't serialize null variables
            string orgJSON = JsonConvert.SerializeObject(newOrg,
                            new JsonSerializerSettings
                            {
                                NullValueHandling = NullValueHandling.Ignore
                            });
            Console.WriteLine(orgJSON);
            
            String newOrgJSON = httpHelper("POST", url, orgJSON);
            newOrg = JsonConvert.DeserializeObject(newOrgJSON);
            return newOrg;
        }
  

Step 3: Get and Update by ID

It is not necessary to download the entire organizational hierarchy every time. Each organization can be retrieved individually.


  #TBD
  
   /*
    * Simple method to retrieve one organization
    */
   private Organization getOrganizationById(String aId){
      String url = baseUrl + "/SCVmcServices/rest/organizations/" + aId;
      try {

         StringBuffer sb = httpHelper("GET", url, null);
         return new Organization(sb.toString());

      } catch (Exception e) {
         System.out.println(e.toString());
      }
      return null;
   }
   
   /*
    * Update an organization.  This illustrates the single property case.  However, 
    * multiple properties can be set at once by including them in the JSON document.
    */
   private void updateOrganization(String aOrgId,
                                   String aPropertyName,
                                   String aPropertyValue) {
      String url = baseUrl + "/SCVmcServices/rest/organizations/" + aOrgId;
      StringBuffer sb = new StringBuffer();
      sb.append("{\""+aPropertyName+"\":\""+aPropertyValue+"\"}");
      String disabledOrg = sb.toString();
      httpHelper("POST", url, disabledOrg);
   }
  
<script>
//TBD
</script>
  

  
/*
* Get one organization by its unique id
*/
private static Organization getOrg(string aOrgId)
{
    String url = BaseUrl + "/SCVmcServices/rest/organizations/" + aOrgId;
    string orgJSON = httpHelper("GET", url, null);
    Organization org = JsonConvert.DeserializeObject(orgJSON);
    return org;
}

/*
 * Update an organization
 */
private static void updateOrg(Organization aOrg)
{
    String url = BaseUrl + "/SCVmcServices/rest/organizations/" + aOrg.identifier;
    string orgJSON = JsonConvert.SerializeObject(aOrg,
        new JsonSerializerSettings
        {
            NullValueHandling = NullValueHandling.Ignore
        });
    httpHelper("POST", url, orgJSON);
}
  

Step 4: Delete Organization by ID

And, of course, the API allows for organization deletion. In order to delete an organization, the child organizations must be deleted and all the accounts in the organization must be deactivated. Proceed with caution when deleting an organization. Make sure you really want to remove it.


  #TBD
  
   /*
    * Delete an organization
    */
   private void deleteOrganization(Organization org) {

      // First disable the organization (cannot delete until this is done)
      String url = baseUrl + "/SCVmcServices/rest/organizations/" + org.myId;
      StringBuffer sb = new StringBuffer();
      // An organization is disabled by setting the enabled flag to false
      sb.append("{\"enabled\":false }");
      String disabledOrg = sb.toString();
      StringBuffer sbOrg = httpHelper("POST", url, disabledOrg);
      // then delete the organization with HTTP DELETE operation
      sbOrg = httpHelper("DELETE", url, null);
   }
  
<script>
//TBD
</script>
  

  
/*
 * Delete an organization. USE WITH CAUTION
 */
 private static void deleteOrg(Organization aOrg)
 {
     String url = BaseUrl + "/SCVmcServices/rest/organizations/" + aOrg.identifier;
     //first disable the org
     aOrg.enabled = false;
     httpHelper("POST", url, JsonConvert.SerializeObject(aOrg));
     //then delete the org
     httpHelper("DELETE", url, JsonConvert.SerializeObject(aOrg));
 }
  
  

Full Sample Code



Below is the full sample code. Copy and paste the entire contents of the code below into your favorite editor and save locally on your machine. Modify the URL's and username/password according to your credentials and system access. Then, run the program and enjoy all the excitement of securely converting audio to text via the nVoq.API platform.


  

  

  

  


If you have any questions, please reach out to support@nvoq.com.

© 2024 nVoq Inc. | Privacy Policy