Pull affiliate deals from GET /api/v1/deals into Excel with copy-paste VBA macrosPull affiliate deals from GET /api/v1/deals into Excel with copy-paste VBA ma...
Use Excel VBA WinHttp and your Hi Energy AI API key to import active affiliate deals into Excel. This guide includes paste-ready code for pagination, JSON:API flattening, and writing rows to a Deals worksheet.
List responses nest records under deals.data (JSON:API). The sample flattens id, type, and attributes into spreadsheet columns.
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. Deals import macro
Paste this into a second standard module, save as .xlsm, then run the
import with Alt+F8.
OptionExplicit' Import affiliate deals into the active workbook.' Requires the shared HiEnergyClient module in this VBA project.' Run: Alt+F8 → ImportHiEnergyDealsPublicSub ImportHiEnergyDeals()
Dim page AsLongDim perPage AsLongDim maxPages AsLongDim allRows As Collection
Dim query AsObjectDim payload AsObjectDim records As Collection
Dim item AsObjectDim count AsLong
page = 1
perPage = 100
maxPages = 20Set allRows = New Collection
DoWhile page <= maxPages
Set query = NewQuery()
query("page") = page
query("per_page") = perPage
query("active") = "true"
query("include_total") = "false"Set payload = HiEnergyApiGet("/api/v1/deals", query)
Set records = ExtractJsonApiCollection(payload, "deals", "data")
If records.Count = 0ThenExitDoForEach item In records
allRows.Add FlattenJsonApiItem(item)
Next item
If records.Count < perPage ThenExitDo
page = page + 1Loop
count = WriteObjectsToSheet("Deals", allRows, True)
MsgBox "Imported " & count & " deals", vbInformation, "Hi Energy AI"EndSub
Useful query parameters
Parameter
Purpose
active
Set true to keep only currently active deals.
exclusive
Filter exclusive offers when supported for your account.
advertiser_id
Limit deals to one advertiser / program.
country
Country or country_code filter for geo-targeted deals.
deal_type
Filter by deal kind / type labels from the deals API.
page / per_page
Offset pagination. The sample walks pages until a short page is returned.
q / search
Free-text search across deal content when needed.
FAQ
Paste the shared VBA client and deals importer from this page, store HIENERGY_API_KEY on a Config sheet, then run ImportHiEnergyDeals. The macro calls GET /api/v1/deals with X-Api-Key and writes flattened rows to a Deals worksheet.
For Hi Energy AI authentication use your personal API key via X-Api-Key. Excel only requires macros enabled and Microsoft Scripting Runtime referenced in the VBA project.
Nested objects and arrays from JSON:API attributes are stringified so every value fits in a single spreadsheet cell. Expand them with VBA or Power Query if you need columnar nested data.
Yes. Edit the sample query parameters such as active, exclusive, advertiser_id, country, deal_type, and search before running ImportHiEnergyDeals. Pagination walks pages until a short page is returned.
Yes. The Excel importer uses the live GET /api/v1/deals endpoint documented on the Deals API page, scoped to your account permissions and rate limits.
Yes. This page publishes TechArticle, HowTo, FAQPage, BreadcrumbList, WebSite SearchAction, and related endpoint ItemList structured data so answer engines can cite a concrete VBA import path.
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.