Management API
Read prices, balance, usage and metrics, revoke AI keys and top up the AI balance with a Helipod API key.
The AI Gateway itself answers model requests with an AI key (hel_ai_...). Everything around it, what the AI Gateway pages of the dashboard show, is available from the AI API with a Helipod API key: prices, the AI balance, usage and charts, your AI keys, and top-ups from the wallet.
https://api.helipod.io/api/aiThe key needs AI API enabled. It is not in a new key's default products: tick it when you create the key. An AI key (hel_ai_...) is not accepted here, and a Helipod API key is not accepted by the gateway.
curl https://api.helipod.io/api/ai/overview \
-H "Authorization: Bearer hel_your_key"Whole account or one project
The AI balance and the wallet belong to your account, so the overview, top-ups and auto top-up need a whole-account key (403 ACCOUNT_KEY_REQUIRED otherwise). Usage, metrics and the key list work with both: a key limited to one project sees that project only, and a whole-account key can narrow them with ?projectId=.
| Method and path | Key | |
|---|---|---|
| Prices | GET /models | any |
| Balance | GET /overview | whole account |
| Usage | GET /usage, GET /metrics | any |
| AI keys | GET /keys, DELETE /keys/{keyId} | any |
| Top up | POST /topup, PUT /auto-topup | whole account |
Creating AI keys stays in the dashboard
The API lists and revokes AI keys but never creates or shows one, so a Helipod key can't be used to mint a key that spends your balance. Create AI keys in the dashboard under AI Gateway.
Prices
/ai/models{
"success": true,
"data": {
"currency": "IDR",
"unit": "per 1M tokens",
"taxPercent": 11,
"models": [
{
"code": "glm-5.3",
"name": "GLM 5.3",
"family": "glm",
"limits": { "context": 200000, "maxInput": 200000, "maxOutput": 32000 },
"capabilities": ["tools", "reasoning"],
"formats": ["openai", "anthropic"],
"peakHours": null,
"currentWindow": "all",
"sunset": null,
"campaign": null,
"tiers": [ { "window": "all", "minInputTokens": 0, "input": 9000, "output": 36000, "cached": 1800, "promo": null } ]
}
]
}
}tiers lists the prices per window (peak and off-peak, when the model has them) and per prompt size (minInputTokens). promo holds the discounted prices of a running promotion that applies to you, described in campaign. See Pricing and billing.
Balance
/ai/overview{
"success": true,
"data": {
"balance": 85000,
"held": 1200,
"freeCredit": 10000,
"available": 93800,
"walletBalance": 482500,
"limitedCredit": [],
"autoTopup": { "enabled": false, "threshold": null, "amount": null, "lastFailedAt": null },
"minTopup": 20000,
"taxPercent": 11,
"currency": "IDR",
"packs": [ { "id": "pack-100k", "name": "Rp 100.000", "amount": 100000, "bonus": 5000 } ],
"coupons": []
}
}Prop
Type
Usage
/ai/usageProp
Type
{
"success": true,
"data": {
"thisMonth": {
"charge": 15230.5,
"saved": 0,
"byModel": [ { "model": "glm-5.3", "requests": 412, "inputTokens": 1210000, "cachedTokens": 380000, "outputTokens": 214000, "charge": 15230.5, "saved": 0 } ]
},
"requests": [
{
"requestId": "req_01JA8Z3K4M",
"createdAt": "2026-10-16T09:12:03.000Z",
"model": "glm-5.3",
"format": "openai",
"stream": true,
"status": "ok",
"projectId": "3b0cd5ac-ac26-4012-9b28-17466f73788c",
"aiKeyId": "5f4e3d2c-1b0a-4f9e-8d7c-6b5a4f3e2d1c",
"inputTokens": 3200, "cachedTokens": 1800, "cacheWriteTokens": 0, "outputTokens": 640,
"priceWindow": "all",
"charge": 54.7,
"listCharge": 54.7,
"latencyMs": 2140,
"promo": null
}
],
"total": 100,
"capped": true,
"page": 1,
"pageSize": 50,
"currency": "IDR"
}
}The request list keeps the latest 100 requests; capped: true means older ones exist. charge is what a request cost you, listCharge what it would have cost without a promotion.
/ai/metricsTakes projectId, keyId and model like usage, and range: 24h (default), 7d or 30d.
{
"success": true,
"data": {
"range": "24h",
"bucket": "hour",
"timezone": "Asia/Jakarta",
"currency": "IDR",
"totals": {
"requests": 412, "ok": 405, "errors": 5, "cancelled": 2, "successRate": 0.983,
"charge": 15230.5, "saved": 0, "promoRequests": 0,
"inputTokens": 1210000, "cachedTokens": 380000, "outputTokens": 214000,
"cacheHitRate": 0.239, "avgLatencyMs": 1980, "p95LatencyMs": 6100
},
"previous": { "requests": 380, "charge": 13900 },
"series": [ { "t": "2026-10-16T09", "requests": 31, "errors": 0, "charge": 1104.2, "inputTokens": 91000, "cachedTokens": 30000, "outputTokens": 16000, "avgLatencyMs": 1870 } ],
"byModel": [ { "model": "glm-5.3", "requests": 412, "charge": 15230.5, "saved": 0, "tokens": 1804000 } ]
}
}previous is the same range just before, for comparison. Buckets are in Western Indonesia Time.
AI keys
/ai/keysprojectId like usage.{
"success": true,
"data": [
{
"id": "5f4e3d2c-1b0a-4f9e-8d7c-6b5a4f3e2d1c",
"name": "production",
"prefix": "hel_ai_Xk3q",
"projectId": "3b0cd5ac-ac26-4012-9b28-17466f73788c",
"status": "active",
"allowedModels": null,
"spendLimitMonthly": 500000,
"lastUsedAt": "2026-10-16T09:12:03.000Z",
"expiresAt": null,
"createdAt": "2026-09-01T08:00:00.000Z"
}
]
}allowedModels is null when the key may use every model.
/ai/keys/{keyId}Returns { "id": "...", "revoked": true }, or 404 KEY_NOT_FOUND. A key limited to one project can revoke only that project's AI keys.
Top up
/ai/topupcharges your walletdryRunIdempotency-KeyProp
Type
Send exactly one of packId or amount (400 INVALID_TOPUP otherwise). See it first with ?dryRun=true:
curl -X POST "https://api.helipod.io/api/ai/topup?dryRun=true" \
-H "Authorization: Bearer hel_your_key" -H "Content-Type: application/json" \
-d '{ "amount": 100000 }'{
"success": true,
"data": {
"dryRun": true,
"currency": "IDR",
"amount": 100000,
"packId": null,
"bonus": 0,
"packBonus": 0,
"campaignBonus": 0,
"walletBalance": 482500,
"walletBalanceAfter": 382500,
"enoughBalance": true,
"aiBalance": 85000,
"aiBalanceAfter": 185000
}
}The real call needs an Idempotency-Key header (400 IDEMPOTENCY_KEY_REQUIRED otherwise), so a retry never moves the money twice:
curl -X POST https://api.helipod.io/api/ai/topup \
-H "Authorization: Bearer hel_your_key" -H "Content-Type: application/json" \
-H "Idempotency-Key: ai-topup-2026-10-16-a1b2" \
-d '{ "amount": 100000 }'{ "success": true, "data": { "dryRun": false, "currency": "IDR", "amount": 100000, "bonus": 0, "campaignBonus": 0, "aiBalance": 185000, "walletBalance": 382500 } }The AI balance can't be moved back to the wallet. A wallet that can't cover it answers 402 INSUFFICIENT_WALLET, an amount below the minimum 400 AMOUNT_TOO_SMALL, an unknown pack 404 PACK_NOT_FOUND. A running top-up bonus is subject to its remaining budget, so the real campaignBonus can be lower than the dry run's.
Auto top-up
/ai/auto-topupdryRunProp
Type
curl -X PUT https://api.helipod.io/api/ai/auto-topup \
-H "Authorization: Bearer hel_your_key" -H "Content-Type: application/json" \
-d '{ "enabled": true, "threshold": 20000, "amount": 100000 }'The response is the overview with the new autoTopup. With ?dryRun=true nothing is saved; the response is { "dryRun": true, "current": { ... }, "next": { ... }, "walletBalance": ..., "currency": "IDR" }. A missing threshold answers 400 INVALID_THRESHOLD, an amount below the minimum 400 AMOUNT_TOO_SMALL.
Errors
| Status | Code | When |
|---|---|---|
401 | NO_API_KEY, INVALID_API_KEY, API_KEY_EXPIRED | Authentication failed |
403 | SCOPE_NOT_ALLOWED | The key was not given the AI API |
403 | ACCOUNT_KEY_REQUIRED | Balance, top-up or auto top-up with a key limited to one project |
400 | INVALID_TOPUP, AMOUNT_TOO_SMALL, INVALID_THRESHOLD, IDEMPOTENCY_KEY_REQUIRED | See above |
402 | INSUFFICIENT_WALLET | The wallet can't cover the top-up |
404 | KEY_NOT_FOUND, PACK_NOT_FOUND, PROJECT_NOT_FOUND | Doesn't exist, or the key can't reach it |
409 | REQUEST_IN_PROGRESS | A top-up with the same Idempotency-Key is still running |
422 | VALIDATION_ERROR | The body or query does not match the schema |