Query data transfer totals
Use this example to aggregate data transfer totals from GET /v0/gateways/{address}/mobile/data/sum. You can request daily buckets by default or switch to hourly buckets when you need higher granularity.
tip
min_time is inclusive. HeliumGeek matches period-based records (like data sums) against their endPeriod, so each line is attributed to the moment the Oracle posted the aggregate. See the time-series guide for details.
Prerequisites
- Node.js 18 or newer (with built-in
fetch). - An API key exported as
HELIUMGEEK_API_KEY. - A gateway address provided as the
GATEWAY_ADDRESSenvironment variable or the first CLI argument.
Run the example
- Download mobile-data-sum.js and save it locally.
- Export the environment variables and choose the bucket size.
Daily buckets (default):
export HELIUMGEEK_API_KEY="your-api-key"
export GATEWAY_ADDRESS="your-gateway-address"
node mobile-data-sum.js
Hourly buckets (48-hour window):
node mobile-data-sum.js <gateway-address> hour
Script
mobile-data-sum.js
#!/usr/bin/env node
const BASE_URL = (process.env.HELIUMGEEK_API_BASE_URL ?? 'https://api.heliumgeek.com/v0').replace(/\/$/, '');
const API_KEY = process.env.HELIUMGEEK_API_KEY;
const GATEWAY_ADDRESS =
(process.argv[2] ?? process.env.GATEWAY_ADDRESS ?? '').trim();
const BUCKET = (process.argv[3] ?? process.env.BUCKET ?? 'day').toLowerCase();
const VALID_BUCKETS = new Set(['day', 'hour']);
const WINDOW_DAYS = 30;
const WINDOW_HOURS = 48;
if (!API_KEY) {
console.error('Set HELIUMGEEK_API_KEY before running this script.');
process.exit(1);
}
if (!GATEWAY_ADDRESS) {
console.error(
'Provide the gateway address as an argument or set GATEWAY_ADDRESS.'
);
process.exit(1);
}
if (!VALID_BUCKETS.has(BUCKET)) {
console.error("Bucket must be 'day' or 'hour'.");
process.exit(1);
}
const byteFormatter = new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
async function main() {
const now = new Date();
const minDate =
BUCKET === 'hour' ? startOfUtcHour(now) : startOfUtcDay(now);
if (BUCKET === 'hour') {
minDate.setUTCHours(minDate.getUTCHours() - WINDOW_HOURS);
} else {
minDate.setUTCDate(minDate.getUTCDate() - WINDOW_DAYS);
}
const response = await fetch(
buildUrl(`/gateways/${encodeURIComponent(GATEWAY_ADDRESS)}/mobile/data/sum`, {
min_time: minDate.toISOString(),
bucket: BUCKET,
}),
{
headers: {
'x-api-key': API_KEY,
},
}
);
if (!response.ok) {
throw new Error(`Request failed: ${response.status} ${response.statusText}`);
}
const sums = (await response.json()) ?? [];
if (sums.length === 0) {
console.log(
`Gateway ${GATEWAY_ADDRESS} transferred no data between ${minDate.toISOString()} and ${now.toISOString()}.`
);
return;
}
sums.sort((a, b) => a.startTimestamp - b.startTimestamp);
console.log(`Data transfer totals for ${GATEWAY_ADDRESS}`);
for (const entry of sums) {
const label = formatLabel(entry.startTimestamp, BUCKET);
const upload = formatBytes(entry.uploadBytesSum);
const download = formatBytes(entry.downloadBytesSum);
const rewardable = formatBytes(entry.rewardableBytesSum);
const rewardableShare =
entry.uploadBytesSum + entry.downloadBytesSum > 0
? (
(Number(entry.rewardableBytesSum) /
(Number(entry.uploadBytesSum) + Number(entry.downloadBytesSum))) *
100
).toFixed(2)
: '0.00';
console.log(
`${label} upload ${upload} download ${download} rewardable ${rewardable} (${rewardableShare}% of total)`
);
if (Array.isArray(entry.carrierBreakdown) && entry.carrierBreakdown.length) {
console.log(' carriers:');
for (const carrier of entry.carrierBreakdown) {
const carrierName = carrier.carrier?.name ?? carrier.carrier?.idString ?? `carrier_${carrier.carrier?.id ?? '?'}`;
const carrierBytes = formatBytes(carrier.rewardableBytes);
console.log(` ${carrierName}: ${carrierBytes} rewardable`);
}
}
}
}
function buildUrl(path, query = {}) {
const url = new URL(path.replace(/^\//, ''), `${BASE_URL}/`);
Object.entries(query).forEach(([key, value]) => {
if (value !== undefined && value !== null && value !== '') {
url.searchParams.set(key, String(value));
}
});
return url.toString();
}
function startOfUtcDay(referenceDate) {
return new Date(
Date.UTC(
referenceDate.getUTCFullYear(),
referenceDate.getUTCMonth(),
referenceDate.getUTCDate()
)
);
}
function startOfUtcHour(referenceDate) {
return new Date(
Date.UTC(
referenceDate.getUTCFullYear(),
referenceDate.getUTCMonth(),
referenceDate.getUTCDate(),
referenceDate.getUTCHours()
)
);
}
function formatLabel(startTimestamp, bucket) {
const iso = new Date(startTimestamp * 1000).toISOString();
if (bucket === 'hour') {
return iso.slice(0, 13) + ':00Z';
}
return iso.slice(0, 10);
}
function formatBytes(bytes) {
const gigabytes = Number(bytes) / 1e9;
return `${byteFormatter.format(gigabytes)} GB`;
}
main().catch((error) => {
console.error(error.message);
process.exit(1);
});