Load affiliate transactions from GET /api/v1/transactions into Excel for analysisLoad affiliate transactions from GET /api/v1/transactions into Excel for anal...
Import affiliate transactions, commissions, and statuses into Excel using VBA macros. The sample defaults to the last 30 days, paginates safely, and flattens JSON:API transaction payloads into a Transactions worksheet.
List responses wrap JSON:API under transactions. Use start_date and end_date for analytics windows; status accepts values such as pending, approved, paid, or corrected.
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. Transactions import macro
Paste this into a second standard module, save as .xlsm, then run the
import with Alt+F8.
OptionExplicit' Import affiliate transactions into Excel.' Requires the shared HiEnergyClient module.' Defaults to the last 30 days. Adjust START_DATE / END_DATE / STATUS as needed.PublicSub ImportHiEnergyTransactions()
Dim START_DATE AsStringDim END_DATE AsStringDim STATUS AsStringDim page AsLongDim perPage AsLongDim maxPages AsLongDim allRows As Collection
Dim query AsObjectDim payload AsObjectDim records As Collection
Dim item AsObjectDim count AsLong
START_DATE = IsoDateDaysAgo(30)
END_DATE = IsoDateToday()
STATUS = ""' e.g. "approved", "pending", "paid", "corrected"
page = 1
perPage = 100
maxPages = 50Set allRows = New Collection
DoWhile page <= maxPages
Set query = NewQuery()
query("start_date") = START_DATE
query("end_date") = END_DATE
query("status") = STATUS
query("page") = page
query("per_page") = perPage
query("include_total") = "false"Set payload = HiEnergyApiGet("/api/v1/transactions", query)
Set records = ExtractJsonApiCollection(payload, "transactions", "data")
If records.Count = 0ThenExitDoForEach item In records
allRows.Add FlattenJsonApiItem(item)
Next item
If records.Count < perPage ThenExitDo
page = page + 1Loop
count = WriteObjectsToSheet("Transactions", allRows, True)
MsgBox "Imported " & count & " transactions", vbInformation, "Hi Energy AI"EndSub
Useful query parameters
Parameter
Purpose
start_date / end_date
Inclusive transaction date bounds (YYYY-MM-DD).
status
pending, approved, paid, corrected (and multi-status where supported).
advertiser_id / advertiser_slug
Limit to one program.
network_id / network_slug
Filter by affiliate network.
currency
ISO currency code such as USD.
sort_by / sort_order
Order results for reporting workflows.
page / per_page
Offset pagination used by the importer loop.
FAQ
Use the paste-ready VBA on this page to call GET /api/v1/transactions with X-Api-Key, paginate results, and write rows to a Transactions worksheet.
Start with the last 30 days sample. Narrow or widen START_DATE and END_DATE for finance closes, publisher reports, or reconciliations.
Transactions search depends on Searchkick/Elasticsearch availability and your publisher scope. Check the Transactions API docs and API status page if requests fail.
Yes. Set STATUS to pending, approved, paid, or corrected, and optionally filter by advertiser_id, network_id / network_slug, currency, and sort_by / sort_order before running the importer.
Yes. Flattened JSON:API attributes typically include commission, sale amount, currency, status, and related advertiser or network fields your account can see.
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.