Import Hi Energy advertiser contacts into Excel with VBA macros. Search by domain, advertiser name, email, or free text, then flatten JSON:API contact records into a Contacts worksheet.
Contacts list responses return JSON:API objects under data. Unverified contacts are excluded unless include_unverified=true is allowed for your account.
Setup in Excel (VBA macros)
Open Excel on Windows (or Excel for Mac with VBA support) and enable the
Developer tab: File → Options → Customize Ribbon → Developer.
Get your personal API key from
API key docs.
Prefer the X-Api-Key header (these samples already do).
Create a worksheet named Config with
HIENERGY_API_KEY in A1 and your key value in B1.
Optionally set HIENERGY_API_BASE in A2 / B2.
Press Alt+F11 → Insert → Module. Paste the shared client library,
then add a second module for the resource import macro below.
In the VBA editor choose Tools → References and enable
Microsoft Scripting Runtime.
Save as a macro-enabled workbook (.xlsm), then run the import with
Alt+F8 (or Developer → Macros).
1. Shared VBA client
Paste this helper library into one standard module once. Every Hi Energy Excel
importer on this site reuses the same WinHttp client, JSON parser,
JSON:API flattener, and sheet writer.
OptionExplicit' Hi Energy AI — shared Excel VBA client (+ JSON helpers)' Paste into ONE standard module named HiEnergyClient.'' Setup:' 1. Enable the Developer tab (File → Options → Customize Ribbon → Developer)' 2. Alt+F11 → Insert → Module → paste this file' 3. Tools → References → check "Microsoft Scripting Runtime"' 4. Create a worksheet named Config with:' A1 = HIENERGY_API_KEY' B1 = your personal API key (https://app.hienergy.ai/api_documentation/api_key)' Optional:' A2 = HIENERGY_API_BASE' B2 = custom host (defaults to https://app.hienergy.ai)' 5. Paste a resource importer module, then run via Alt+F8'' Trust note: enable macros only for workbooks you created. Do not commit API keys to shared files.PublicConst HIENERGY_API_BASE_DEFAULT AsString = "https://app.hienergy.ai"PublicFunction GetHiEnergyApiKey() AsStringDim key AsString
key = Trim$(CStr(NzConfig("HIENERGY_API_KEY")))
If Len(key) = 0Then
Err.Raise vbObjectError + 1001, "HiEnergyClient", _
"Missing Config API key. Put HIENERGY_API_KEY in Config!A1 and your key in Config!B1."EndIf
GetHiEnergyApiKey = key
EndFunctionPublicFunction GetHiEnergyApiBase() AsStringDim base AsString
base = Trim$(CStr(NzConfig("HIENERGY_API_BASE")))
If Len(base) = 0Then base = HIENERGY_API_BASE_DEFAULT
If Right$(base, 1) = "/"Then base = Left$(base, Len(base) - 1)
GetHiEnergyApiBase = base
EndFunctionPrivateFunction NzConfig(ByVal keyName AsString) AsVariantDim ws As Worksheet
Dim lastRow AsLongDim r AsLong
On ErrorResumeNextSet ws = ThisWorkbook.Worksheets("Config")
On ErrorGoTo0If ws Is NothingThen
NzConfig = ""ExitFunctionEndIf
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
For r = 1To Application.Max(1, lastRow)
If StrComp(Trim$(CStr(ws.Cells(r, 1).Value)), keyName, vbTextCompare) = 0Then
NzConfig = ws.Cells(r, 2).Value
ExitFunctionEndIfNext r
NzConfig = ""EndFunctionPublicFunction NewQuery() AsObjectSet NewQuery = CreateObject("Scripting.Dictionary")
EndFunctionPublicFunction HiEnergyApiGet(ByVal path AsString, OptionalByVal query AsObject = Nothing) AsObjectDim url AsStringDim http AsObjectDim body AsStringDim status AsLongDim parsed AsObjectDim message AsString
url = GetHiEnergyApiBase() & path
IfNot query Is NothingThen url = url & BuildQueryString(query)
Set http = CreateObject("WinHttp.WinHttpRequest.5.1")
http.Open "GET", url, False
http.SetRequestHeader "X-Api-Key", GetHiEnergyApiKey()
http.SetRequestHeader "Accept", "application/json"
http.Send
status = CLng(http.Status)
body = CStr(http.ResponseText)
Set parsed = ParseJson(body)
If status < 200Or status >= 300Then
message = body
IfNot parsed Is NothingThenIf parsed.Exists("error") Then message = CStr(parsed("error"))
If parsed.Exists("message") Then message = CStr(parsed("message"))
EndIf
Err.Raise vbObjectError + 1002, "HiEnergyClient", "Hi Energy AI API HTTP " & status & ": " & message
EndIfSet HiEnergyApiGet = parsed
EndFunctionPrivateFunction BuildQueryString(ByVal query AsObject) AsStringDim key AsVariantDim first AsBooleanDim out AsStringDim value AsString
first = True
out = ""ForEach key In query.Keys
value = Trim$(CStr(query(key)))
If Len(value) > 0ThenIf first Then
out = "?"
first = FalseElse
out = out & "&"EndIf
out = out & UrlEncode(CStr(key)) & "=" & UrlEncode(value)
EndIfNext key
BuildQueryString = out
EndFunctionPrivateFunction UrlEncode(ByVal value AsString) AsStringDim i AsLongDim ch AsStringDim code AsIntegerDim out AsStringFor i = 1To Len(value)
ch = Mid$(value, i, 1)
code = Asc(ch)
SelectCase code
Case48To57, 65To90, 97To122, 45, 46, 95, 126
out = out & ch
Case32
out = out & "%20"CaseElse
out = out & "%" & Right$("0" & Hex$(code), 2)
EndSelectNext i
UrlEncode = out
EndFunctionPublicFunction FlattenJsonApiItem(ByVal item AsObject) AsObjectDim row AsObjectDim attrs AsObjectDim key AsVariantSet row = CreateObject("Scripting.Dictionary")
If item Is NothingThenSet FlattenJsonApiItem = row
ExitFunctionEndIfIf item.Exists("id") Then row("id") = Scalarize(item("id"))
If item.Exists("type") Then row("type") = Scalarize(item("type"))
If item.Exists("attributes") ThenIf TypeName(item("attributes")) = "Dictionary"ThenSet attrs = item("attributes")
ForEach key In attrs.Keys
row(CStr(key)) = Scalarize(attrs(key))
Next key
EndIfEndIfSet FlattenJsonApiItem = row
EndFunctionPublicFunction FlattenFlatItem(ByVal item AsObject) AsObjectDim row AsObjectDim key AsVariantSet row = CreateObject("Scripting.Dictionary")
If item Is NothingThenSet FlattenFlatItem = row
ExitFunctionEndIfForEach key In item.Keys
row(CStr(key)) = Scalarize(item(key))
Next key
Set FlattenFlatItem = row
EndFunctionPrivateFunction Scalarize(ByVal value AsVariant) AsVariantIf IsObject(value) Then
Scalarize = JsonStringify(value)
ElseIf IsNull(value) Or IsEmpty(value) Then
Scalarize = ""Else
Scalarize = value
EndIfEndFunctionPublicFunction ExtractJsonApiCollection(ByVal payload AsObject, ParamArray preferredKeys() AsVariant) As Collection
Dim i AsLongDim key AsStringDim node AsObjectDim emptyCol As Collection
Set emptyCol = New Collection
If payload Is NothingThenSet ExtractJsonApiCollection = emptyCol
ExitFunctionEndIfIf UBound(preferredKeys) >= LBound(preferredKeys) ThenFor i = LBound(preferredKeys) To UBound(preferredKeys)
key = CStr(preferredKeys(i))
If payload.Exists(key) ThenIf TypeName(payload(key)) = "Collection"ThenSet ExtractJsonApiCollection = payload(key)
ExitFunctionEndIfIf TypeName(payload(key)) = "Dictionary"ThenSet node = payload(key)
If node.Exists("data") ThenIf TypeName(node("data")) = "Collection"ThenSet ExtractJsonApiCollection = node("data")
ExitFunctionEndIfEndIfEndIfEndIfNext i
EndIfIf payload.Exists("data") ThenIf TypeName(payload("data")) = "Collection"ThenSet ExtractJsonApiCollection = payload("data")
ExitFunctionEndIfEndIfSet ExtractJsonApiCollection = emptyCol
EndFunctionPublicFunction WriteObjectsToSheet(ByVal sheetName AsString, ByVal rows As Collection, OptionalByVal clearSheet AsBoolean = True) AsLongDim ws As Worksheet
Dim headers As Collection
Dim seen AsObjectDim rowDict AsObjectDim key AsVariantDim r AsLongDim c AsLong
On ErrorResumeNextSet ws = ThisWorkbook.Worksheets(sheetName)
On ErrorGoTo0If ws Is NothingThenSet ws = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Worksheets(ThisWorkbook.Worksheets.Count))
On ErrorResumeNext
ws.Name = sheetName
On ErrorGoTo0EndIfIf clearSheet Then ws.Cells.ClearContents
If rows Is NothingOr rows.Count = 0Then
ws.Range("A1").Value = "No rows returned"
WriteObjectsToSheet = 0ExitFunctionEndIfSet headers = New Collection
Set seen = CreateObject("Scripting.Dictionary")
ForEach rowDict In rows
ForEach key In rowDict.Keys
IfNot seen.Exists(CStr(key)) Then
headers.Add CStr(key)
seen(CStr(key)) = TrueEndIfNext key
Next rowDict
For c = 1To headers.Count
ws.Cells(1, c).Value = headers(c)
Next c
r = 2ForEach rowDict In rows
For c = 1To headers.Count
If rowDict.Exists(headers(c)) Then
ws.Cells(r, c).Value = rowDict(headers(c))
EndIfNext c
r = r + 1Next rowDict
ws.Rows(1).Font.Bold = True
WriteObjectsToSheet = rows.Count
EndFunctionPublicFunction IsoDateDaysAgo(ByVal days AsLong) AsString
IsoDateDaysAgo = Format$(Date - days, "yyyy-mm-dd")
EndFunctionPublicFunction IsoDateToday() AsString
IsoDateToday = Format$(Date, "yyyy-mm-dd")
EndFunctionPublicFunction JsonStringify(ByVal value AsVariant) AsStringDim key AsVariantDim i AsLongDim parts() AsStringDim n AsLongDim item AsVariantIf IsObject(value) ThenIf TypeName(value) = "Dictionary"Then
n = 0If value.Count = 0Then
JsonStringify = "{}"ExitFunctionEndIf
ReDim parts(0To value.Count - 1)
ForEach key In value.Keys
parts(n) = JsonEscape(CStr(key)) & ":" & JsonStringify(value(key))
n = n + 1Next key
JsonStringify = "{" & Join(parts, ",") & "}"ExitFunctionEndIfIf TypeName(value) = "Collection"ThenIf value.Count = 0Then
JsonStringify = "[]"ExitFunctionEndIf
ReDim parts(1To value.Count)
i = 1ForEach item In value
parts(i) = JsonStringify(item)
i = i + 1Next item
JsonStringify = "[" & Join(parts, ",") & "]"ExitFunctionEndIfEndIfIf IsNull(value) Or IsEmpty(value) Then
JsonStringify = "null"ElseIf VarType(value) = vbBoolean Then
JsonStringify = IIf(value, "true", "false")
ElseIf IsNumeric(value) And VarType(value) <> vbString Then
JsonStringify = Replace$(CStr(value), ",", ".")
Else
JsonStringify = JsonEscape(CStr(value))
EndIfEndFunctionPrivateFunction JsonEscape(ByVal value AsString) AsString
value = Replace$(value, "\", "\\")
value = Replace$(value, """", "\""")
value = Replace$(value, vbCr, "\r")
value = Replace$(value, vbLf, "\n")
value = Replace$(value, vbTab, "\t")
JsonEscape = """" & value & """"EndFunctionPublicFunction ParseJson(ByVal jsonText AsString) AsObjectDim p AsLong
p = 1Set ParseJson = ParseJsonValue(jsonText, p)
EndFunctionPrivateFunction ParseJsonValue(ByRef text AsString, ByRef p AsLong) AsVariant
SkipWs text, p
SelectCase Mid$(text, p, 1)
Case"{"Set ParseJsonValue = ParseJsonObject(text, p)
Case"["Set ParseJsonValue = ParseJsonArray(text, p)
Case""""
ParseJsonValue = ParseJsonString(text, p)
Case"t"If Mid$(text, p, 4) <> "true"Then Err.Raise vbObjectError + 1100, , "Invalid JSON boolean"
p = p + 4
ParseJsonValue = TrueCase"f"If Mid$(text, p, 5) <> "false"Then Err.Raise vbObjectError + 1100, , "Invalid JSON boolean"
p = p + 5
ParseJsonValue = FalseCase"n"If Mid$(text, p, 4) <> "null"Then Err.Raise vbObjectError + 1100, , "Invalid JSON null"
p = p + 4
ParseJsonValue = Null
CaseElse
ParseJsonValue = ParseJsonNumber(text, p)
EndSelectEndFunctionPrivateFunction ParseJsonObject(ByRef text AsString, ByRef p AsLong) AsObjectDim dict AsObjectDim key AsStringDim value AsVariantSet dict = CreateObject("Scripting.Dictionary")
p = p + 1
SkipWs text, p
If Mid$(text, p, 1) = "}"Then
p = p + 1Set ParseJsonObject = dict
ExitFunctionEndIfDo
SkipWs text, p
key = ParseJsonString(text, p)
SkipWs text, p
If Mid$(text, p, 1) <> ":"Then Err.Raise vbObjectError + 1101, , "Expected :"
p = p + 1
value = ParseJsonValue(text, p)
If IsObject(value) ThenSet dict(key) = value
Else
dict(key) = value
EndIf
SkipWs text, p
If Mid$(text, p, 1) = ","Then
p = p + 1ElseExitDoEndIfLoop
SkipWs text, p
If Mid$(text, p, 1) <> "}"Then Err.Raise vbObjectError + 1102, , "Expected }"
p = p + 1Set ParseJsonObject = dict
EndFunctionPrivateFunction ParseJsonArray(ByRef text AsString, ByRef p AsLong) As Collection
Dim col As Collection
Dim value AsVariantSet col = New Collection
p = p + 1
SkipWs text, p
If Mid$(text, p, 1) = "]"Then
p = p + 1Set ParseJsonArray = col
ExitFunctionEndIfDo
value = ParseJsonValue(text, p)
If IsObject(value) Then
col.Add value
Else
col.Add value
EndIf
SkipWs text, p
If Mid$(text, p, 1) = ","Then
p = p + 1ElseExitDoEndIfLoop
SkipWs text, p
If Mid$(text, p, 1) <> "]"Then Err.Raise vbObjectError + 1103, , "Expected ]"
p = p + 1Set ParseJsonArray = col
EndFunctionPrivateFunction ParseJsonString(ByRef text AsString, ByRef p AsLong) AsStringDim out AsStringDim ch AsStringIf Mid$(text, p, 1) <> """"Then Err.Raise vbObjectError + 1104, , "Expected string"
p = p + 1DoWhile p <= Len(text)
ch = Mid$(text, p, 1)
p = p + 1If ch = """"Then
ParseJsonString = out
ExitFunctionEndIfIf ch = "\"Then
ch = Mid$(text, p, 1)
p = p + 1SelectCase ch
Case"""", "\", "/"
out = out & ch
Case"b"
out = out & vbBack
Case"f"
out = out & vbFormFeed
Case"n"
out = out & vbLf
Case"r"
out = out & vbCr
Case"t"
out = out & vbTab
Case"u"
out = out & ChrW$("&H" & Mid$(text, p, 4))
p = p + 4CaseElse
out = out & ch
EndSelectElse
out = out & ch
EndIfLoop
Err.Raise vbObjectError + 1105, , "Unterminated string"EndFunctionPrivateFunction ParseJsonNumber(ByRef text AsString, ByRef p AsLong) AsVariantDim startPos AsLongDim ch AsStringDim raw AsString
startPos = p
ch = Mid$(text, p, 1)
If ch = "-"Then p = p + 1DoWhile p <= Len(text)
ch = Mid$(text, p, 1)
If (ch >= "0"And ch <= "9") Or ch = "."Or ch = "e"Or ch = "E"Or ch = "+"Or ch = "-"Then
p = p + 1ElseExitDoEndIfLoop
raw = Mid$(text, startPos, p - startPos)
If InStr(raw, ".") > 0Or InStr(1, raw, "e", vbTextCompare) > 0Then
ParseJsonNumber = CDbl(Val(raw))
Else
ParseJsonNumber = CLng(Val(raw))
EndIfEndFunctionPrivateSub SkipWs(ByRef text AsString, ByRef p AsLong)
DoWhile p <= Len(text)
SelectCase Mid$(text, p, 1)
Case" ", vbTab, vbCr, vbLf
p = p + 1CaseElseExitDoEndSelectLoopEndSub
2. Contacts import macro
Paste this into a second standard module, save as .xlsm, then run the
import with Alt+F8.
OptionExplicit' Import Hi Energy contacts into Excel.' Requires the shared HiEnergyClient module.' Search by domain, advertiser name, email, or free-text q.PublicSub ImportHiEnergyContacts()
Dim DOMAIN AsStringDim ADVERTISER_NAME AsStringDim EMAIL AsStringDim QUERY AsStringDim page AsLongDim perPage AsLongDim maxPages AsLongDim allRows As Collection
Dim query AsObjectDim payload AsObjectDim records As Collection
Dim item AsObjectDim count AsLong
DOMAIN = ""' e.g. "nike.com"
ADVERTISER_NAME = ""' e.g. "Nike"
EMAIL = ""
QUERY = ""
page = 1
perPage = 100
maxPages = 20Set allRows = New Collection
DoWhile page <= maxPages
Set query = NewQuery()
query("domain") = DOMAIN
query("advertiser_name") = ADVERTISER_NAME
query("email") = EMAIL
query("q") = QUERY
query("page") = page
query("per_page") = perPage
Set payload = HiEnergyApiGet("/api/v1/contacts", query)
Set records = ExtractJsonApiCollection(payload, "data")
If records.Count = 0ThenExitDoForEach item In records
allRows.Add FlattenJsonApiItem(item)
Next item
If records.Count < perPage ThenExitDo
page = page + 1Loop
count = WriteObjectsToSheet("Contacts", allRows, True)
MsgBox "Imported " & count & " contacts", vbInformation, "Hi Energy AI"EndSub
Useful query parameters
Parameter
Purpose
domain
Find contacts for an advertiser website domain.
advertiser_name
Match contacts by program / brand name.
advertiser_id
Exact advertiser id scope.
email
Look up a specific contact email.
q
Free-text search across contact fields.
has_linkedin
Prefer contacts that include LinkedIn profile URLs.
include_unverified
Include unverified contacts when your role allows it.
FAQ
Use the VBA samples on this page to call GET /api/v1/contacts with your API key and write flattened contact attributes to a Contacts worksheet.
Domain is usually most precise for a brand website. Advertiser name is useful for fuzzy discovery. You can combine filters.
Creating contacts uses POST /api/v1/contacts and requires create permissions (admin/paid publisher on REST). This page focuses on read/import workflows; see the Contacts API docs for create payloads.
No. Unverified contacts are excluded unless include_unverified=true is allowed for your account and you enable that filter in the importer.
Yes. Set has_linkedin in the sample filters when you want outreach lists that include LinkedIn URLs.
Yes. This page publishes TechArticle, HowTo, FAQPage, BreadcrumbList, WebSite SearchAction, and related endpoint ItemList structured data for answer engines.
Ask Dex AIIntegration help
If this page feels TLDR, ask Dex AI.
Dex AI speaks your language, and all the other languages you may not. It will write the integration for you with the right endpoint and headers in one plain-English answer.