Importing Files and Data Using the Hunni API (Doc Library pt. 2)

This guide walks through an example of how to bulk import files and data to a document library using the Hunni API.  The content and code is based on the example document library from the following video guide (watch that video before following this guide):

How to Build a Secure Document Library in Hunni (Video Guide) →

This example was written in C# and the full program will run as a .NET framework 4.8 console app that requires the Newtonsoft JSON framework.  You can install it through the command: Install-Package Newtonsoft.Json

1. Get API Credentials

The first thing you need to do is to get API credentials.  All paid accounts can access the API.  Business account admins must permission API access from their account settings.

See guide for creating your API credentials →

2. Get Your Table ID

You will need to Hunni table ID of the table you are going to import data and files to. Here is how you find it:

  1. Navigate to Expanded Grid in your table.
  2. Open the menu (☰) at the top right of the table and click Show Id.
  3. Copy the Asset ID — this is your table’s unique identifier.

3. Get an Access Token

To interact with the Hunni Rest API, you first need to get a token.  That can be achieved with the following code.

string strClientId = "<your Client ID>";
string strClientSecret = "<your Client Secret>";
string strToken = null;

using (HttpClient client = new HttpClient())
{
    var request = new HttpRequestMessage(HttpMethod.Post, "https://api.hunni.io/oauth/token")
    {
        Content = new StringContent($"grant_type=client_credentials&client_id={strClientId}&client_secret={strClientSecret}")
    };

    var response = client.SendAsync(request).Result;
    var result = JsonConvert.DeserializeObject<dynamic>(response.Content.ReadAsStringAsync().Result);
    strToken = result.access_token;
}

4. Create Objects

Our code needs some objects created so that we can cast the json to make it easier.  You will want to add these to your project.

public class HunniListValue
 {
     public int Id { get; set; }
     public string Value { get; set; }
 }
 public class HunniRow
 {
     public enum HunniAssetType { Table, FileGroup }
     public int Id;
     public int HunniAssetId;
     public List<HunniRowColumnValue> HunniRowColumnValues;
     public HunniAssetType AssetType;
 }
 public class HunniRowColumnValue
 {
     public int HunniRowId;
     public int HunniColumnId;
     public List<string> Values;
 }
 public class HunniFile
 {
     public int Id;
     public string Name;
     public Int64 Length;
 }
 public class HunniResult
 {
     public string Message;
     public bool IsSuccess;
     public int ObjectId;
 }
 public class HunniTable
 {
     public enum HunniTableAccess { Owner, Write, Read }
     public int Id;
     public string Name;
     public int HunniFolderId;
     public HunniTableAccess Access;
     public string Description;
     public DateTime LastUpdatedOn;
     public List<HunniColumn> HunniColumns;
 }
     public class HunniColumn
 {
     public int Id;
     public int HunniAssetId;
     public int AssetTypeId;
     public string Name;
     public int HunniColumnTypeId;
     public bool IsRequired;
     public int DisplayOrder;
 }

5. Create Helper Methods

Call REST Method

public static string CallRestMethod(string url, string token)
{
    try
    {
        var myUri = new Uri(url);
        var myWebRequest = WebRequest.Create(myUri);
        var myHttpWebRequest = (HttpWebRequest)myWebRequest;
        myHttpWebRequest.Headers.Add("Authorization", "Bearer " + token);
        var myWebResponse = myWebRequest.GetResponse();
        Encoding enc = System.Text.Encoding.GetEncoding("utf-8");
        StreamReader responseStream = new StreamReader(myWebResponse.GetResponseStream(), enc);
        string result = string.Empty;
        result = responseStream.ReadToEnd();
        myWebResponse.Close();
        return result;
    }
    catch
    {
        return null;
    }
}

Get a Hunni Table

public static HunniTable GetHunniTableById(int id, string token)
{
    string json = CallRestMethod($"https://api.hunni.io/v1/HunniTable/{id}", token);
    return JsonConvert.DeserializeObject<HunniTable>(json);
}

Get Metadata (List Values)

public static List<HunniListValue> GetHunniListItemValuesById(int id, string token)
{
    string json = CallRestMethod($"https://api.hunni.io/v1/HunniListValues/{id}", token);
    return JsonConvert.DeserializeObject<List<HunniListValue>>(json);
}

Post to API

public static HunniResult PostJsonToWebAPI(string url, string json, string token)
{
    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
    var content = new StringContent(json, Encoding.UTF8, "application/json");
    var response = client.PostAsync(url, content).Result;
    return JsonConvert.DeserializeObject<HunniResult>(response.Content.ReadAsStringAsync().Result);
}

Upload a File

public static int UploadFile(string path, string filename, string token)
{
    var client = new HttpClient();
    var content = new MultipartFormDataContent();
    content.Add(new StreamContent(File.OpenRead(path + filename)), "file", filename);
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
    var response = client.PostAsync("https://api.hunni.io/v1/HunniFileBinary", content).Result;
    var result = JsonConvert.DeserializeObject<HunniResult>(response.Content.ReadAsStringAsync().Result);
    return result.IsSuccess ? result.ObjectId : -1;
}

6. Map Column and Metadata IDs

int iTableId = "<your Table ID>";
int iCompanyColumnId = 0;
int iInvestmentColumnId = 0;
int iDocumentTypeColumnId = 0;
int iQuarterColumnId = 0;
int iDocumentColumnId = 0;

HunniTable table = GetHunniTableById(iTableId, strToken);
foreach (HunniColumn col in table.HunniColumns)
{
    switch (col.Name)
    {
        case "Company": iCompanyColumnId = col.Id; break;
        case "Investment": iInvestmentColumnId = col.Id; break;
        case "Document Type": iDocumentTypeColumnId = col.Id; break;
        case "Quarter": iQuarterColumnId = col.Id; break;
        case "Document": iDocumentColumnId = col.Id; break;
    }
}

Also build dictionaries for metadata values:

var lCompanies = GetHunniListItemValuesById(iCompanyColumnId, strToken);
var lInvestments = GetHunniListItemValuesById(iInvestmentColumnId, strToken);
var lDocTypes = GetHunniListItemValuesById(iDocumentTypeColumnId, strToken);
var lQuarters = GetHunniListItemValuesById(iQuarterColumnId, strToken);

var dCompanyMap = lCompanies.ToDictionary(x => x.Value, x => x);
var dInvestmentMap = lInvestments.ToDictionary(x => x.Value, x => x);
var dDocTypeMap = lDocTypes.ToDictionary(x => x.Value, x => x);
var dQuarterMap = lQuarters.ToDictionary(x => x.Value, x => x);

7. Upload and Save Data

Upload File

int iFileId = UploadFile(@"C:\temp\", "Workbook.xlsx", strToken);

Create and Save a Row

var row = new HunniRow {
    HunniAssetId = iTableId,
    AssetType = HunniRow.HunniAssetType.Table,
    HunniRowColumnValues = new List<HunniRowColumnValue> {
        new HunniRowColumnValue { HunniColumnId = iCompanyColumnId, Values = new List<string>{ dCompanyMap["SkyVision"].Id.ToString() } },
        new HunniRowColumnValue { HunniColumnId = iInvestmentColumnId, Values = new List<string>{ dInvestmentMap["Peakstone Investments"].Id.ToString() } },
        new HunniRowColumnValue { HunniColumnId = iDocumentTypeColumnId, Values = new List<string>{ dDocTypeMap["Expense Report"].Id.ToString() } },
        new HunniRowColumnValue { HunniColumnId = iQuarterColumnId, Values = new List<string>{ dQuarterMap["Q4 2009"].Id.ToString() } },
        new HunniRowColumnValue { HunniColumnId = iDocumentColumnId, Values = new List<string>{ iFileId.ToString() } },
    }
};

var result = PostJsonToWebAPI("https://api.hunni.io/v1/HunniRowSave", JsonConvert.SerializeObject(row), strToken);

That’s it! Executing the full program will result in the file being uploaded and the row with metadata being saved to the table.

If you have questions, please contact us at support@hunni.io.

Full Program

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using Newtonsoft.Json;
using System.Linq;

namespace DocumentPortalDemo
{
    internal class Program
    {
        static string strClientId = "<your Client ID>";
        static string strClientSecret = "<your Client Secret>";
        static string strToken = null;

        static void Main(string[] args)
        {

            GetToken();

            int iTableId = "<your Table ID>";
            int iCompanyColumnId = 0;
            int iInvestmentColumnId = 0;
            int iDocumentTypeColumnId = 0;
            int iQuarterColumnId = 0;
            int iDocumentColumnId = 0;

            HunniTable table = GetHunniTableById(iTableId, strToken);
            foreach (HunniColumn col in table.HunniColumns)
            {
                switch (col.Name)
                {
                    case "Company": iCompanyColumnId = col.Id; break;
                    case "Investment": iInvestmentColumnId = col.Id; break;
                    case "Document Type": iDocumentTypeColumnId = col.Id; break;
                    case "Quarter": iQuarterColumnId = col.Id; break;
                    case "Document": iDocumentColumnId = col.Id; break;
                }
            }

            var lCompanies = GetHunniListItemValuesById(iCompanyColumnId, strToken);
            var lInvestments = GetHunniListItemValuesById(iInvestmentColumnId, strToken);
            var lDocTypes = GetHunniListItemValuesById(iDocumentTypeColumnId, strToken);
            var lQuarters = GetHunniListItemValuesById(iQuarterColumnId, strToken);
            var dCompanyMap = lCompanies.ToDictionary(x => x.Value, x => x);
            var dInvestmentMap = lInvestments.ToDictionary(x => x.Value, x => x);
            var dDocTypeMap = lDocTypes.ToDictionary(x => x.Value, x => x);
            var dQuarterMap = lQuarters.ToDictionary(x => x.Value, x => x);
            
            int iFileId = UploadFile(@"c:\temp\", "Workbook.xlsx", strToken);

            var row = new HunniRow
            {
                HunniAssetId = iTableId,
                AssetType = HunniRow.HunniAssetType.Table,
                HunniRowColumnValues = new List<HunniRowColumnValue> {
                    new HunniRowColumnValue { HunniColumnId = iCompanyColumnId, Values = new List<string>{ dCompanyMap["SkyVision"].Id.ToString() } },
                    new HunniRowColumnValue { HunniColumnId = iInvestmentColumnId, Values = new List<string>{ dInvestmentMap["Peakstone Investments"].Id.ToString() } },
                    new HunniRowColumnValue { HunniColumnId = iDocumentTypeColumnId, Values = new List<string>{ dDocTypeMap["Expense Report"].Id.ToString() } },
                    new HunniRowColumnValue { HunniColumnId = iQuarterColumnId, Values = new List<string>{ dQuarterMap["Q4 2009"].Id.ToString() } },
                    new HunniRowColumnValue { HunniColumnId = iDocumentColumnId, Values = new List<string>{ iFileId.ToString() } },
                }
            };

            var result = PostJsonToWebAPI("https://api.hunni.io/v1/HunniRowSave", JsonConvert.SerializeObject(row), strToken);
        }

        private static string GetToken()
        {
            using (HttpClient client = new HttpClient())
            {
                var request = new HttpRequestMessage(HttpMethod.Post, "https://api.hunni.io/oauth/token")
                {
                    Content = new StringContent($"grant_type=client_credentials&client_id={strClientId}&client_secret={strClientSecret}")
                };

                var response = client.SendAsync(request).Result;
                var result = JsonConvert.DeserializeObject<dynamic>(response.Content.ReadAsStringAsync().Result);
                strToken = result.access_token;
            }
            return strToken;
        }

        public static string CallRestMethod(string url, string token)
        {
            try
            {
                var myUri = new Uri(url);
                var myWebRequest = WebRequest.Create(myUri);
                var myHttpWebRequest = (HttpWebRequest)myWebRequest;
                myHttpWebRequest.Headers.Add("Authorization", "Bearer " + token);
                var myWebResponse = myWebRequest.GetResponse();
                Encoding enc = System.Text.Encoding.GetEncoding("utf-8");
                StreamReader responseStream = new StreamReader(myWebResponse.GetResponseStream(), enc);
                string result = string.Empty;
                result = responseStream.ReadToEnd();
                myWebResponse.Close();
                return result;
            }
            catch
            {
                return null;
            }
        }

        public static HunniTable GetHunniTableById(int id, string token)
        {
            string json = CallRestMethod($"https://api.hunni.io/v1/HunniTable/{id}", token);
            return JsonConvert.DeserializeObject<HunniTable>(json);
        }

        public static List<HunniListValue> GetHunniListItemValuesById(int id, string token)
        {
            string json = CallRestMethod($"https://api.hunni.io/v1/HunniListValues/{id}", token);
            return JsonConvert.DeserializeObject<List<HunniListValue>>(json);
        }

        public static HunniResult PostJsonToWebAPI(string url, string json, string token)
        {
            var client = new HttpClient();
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
            var content = new StringContent(json, Encoding.UTF8, "application/json");
            var response = client.PostAsync(url, content).Result;
            return JsonConvert.DeserializeObject<HunniResult>(response.Content.ReadAsStringAsync().Result);
        }

        public static int UploadFile(string path, string filename, string token)
        {
            var client = new HttpClient();
            var content = new MultipartFormDataContent();
            content.Add(new StreamContent(File.OpenRead(path + filename)), "file", filename);
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
            var response = client.PostAsync("https://api.hunni.io/v1/HunniFileBinary", content).Result;
            var result = JsonConvert.DeserializeObject<HunniResult>(response.Content.ReadAsStringAsync().Result);
            return result.IsSuccess ? result.ObjectId : -1;
        }
        public class HunniListValue
        {
            public int Id { get; set; }
            public string Value { get; set; }
        }
        public class HunniRow
        {
            public enum HunniAssetType { Table, FileGroup }
            public int Id;
            public int HunniAssetId;
            public List<HunniRowColumnValue> HunniRowColumnValues;
            public HunniAssetType AssetType;
        }
        public class HunniRowColumnValue
        {
            public int HunniRowId;
            public int HunniColumnId;
            public List<string> Values;
        }
        public class HunniFile
        {
            public int Id;
            public string Name;
            public Int64 Length;
        }
        public class HunniResult
        {
            public string Message;
            public bool IsSuccess;
            public int ObjectId;
        }
        public class HunniTable
        {
            public enum HunniTableAccess { Owner, Write, Read }
            public int Id;
            public string Name;
            public int HunniFolderId;
            public HunniTableAccess Access;
            public string Description;
            public DateTime LastUpdatedOn;
            public List<HunniColumn> HunniColumns;
        }
        public class HunniColumn
        {
            public int Id;
            public int HunniAssetId;
            public int AssetTypeId;
            public string Name;
            public int HunniColumnTypeId;
            public bool IsRequired;
            public int DisplayOrder;
        }

    }
}