Billing Reconciliation & Automated Usage Sync

If you want to feed AIone spend data into your own finance / monitoring system (daily reconciliation, balance alerts, per-model cost allocation), there is no need to log into the console and export by hand. The platform offers two programmatic query channels — combine them as needed for fully automated reconciliation:

Channel Credential Best for
① API-token direct query (/v1/dashboard/billing/*) Your sk-nex- API token Balance monitoring, quota alerts, month-to-date spend. Zero login; works out of the box with one-api / new-api ecosystem balance-checker tools
② Account login for details (/api/v1/obs/*, /api/v1/billing/*) Console account (email + password) Line-item reconciliation: aggregation by day / model / key, CSV / XLSX export, ledger and invoices

Reconciliation basis: both channels read the same billing facts (the per-request usage_ledger). All amounts are in USD, and month boundaries follow your organization's configured timezone. The sum of per-request cost_usd in the detail export equals the invoice amount — there is no second set of books.

Base URL: https://api.portal.aiin1.ai. Authentication is identical to model calls (Authorization: Bearer sk-nex-..., subject to the API key's IP allowlist). Responses use the OpenAI-compatible format.

1.1 Credit summary: GET /v1/dashboard/billing/credit_grants

curl https://api.portal.aiin1.ai/v1/dashboard/billing/credit_grants \
  -H "Authorization: Bearer sk-nex-your-key-here"
{
  "object": "credit_summary",
  "total_granted": 1000.0,
  "total_used": 137.42,
  "total_available": 862.58,
  "grants": { "object": "list", "data": [] }
}

Field semantics depend on your billing mode:

Billing mode total_available total_used total_granted
prepaid real-time available balance month-to-date spend balance + month-to-date spend
postpaid / hybrid credit limit − current exposure current exposure (= month cost − confirmed payments this month) credit limit

1.2 Subscription / quota: GET /v1/dashboard/billing/subscription

curl https://api.portal.aiin1.ai/v1/dashboard/billing/subscription \
  -H "Authorization: Bearer sk-nex-your-key-here"
{
  "object": "billing_subscription",
  "has_payment_method": true,
  "soft_limit_usd": 862.58,
  "hard_limit_usd": 862.58,
  "system_hard_limit_usd": 862.58,
  "plan": { "title": "prepaid", "id": "prepaid" }
}

hard_limit_usd is your current spending cap: the credit limit for postpaid / hybrid, or the current available balance for prepaid.

These endpoints mirror OpenAI's legacy billing API, so any tool that can "check an OpenAI balance" (browser extensions, new-api / one-api channel balance monitors, etc.) works by pointing its base URL at https://api.portal.aiin1.ai.

2. Account login for line-item details (reconciliation / export)

Detail data lives under the console backend API, base URL https://portal.aiin1.ai/api/v1. Auth is a short-lived session token: log in once with a console account, receive an access_token valid for 15 minutes, and complete all pulls within that window — no token-refresh logic needed.

Recommendation: create a dedicated regular-member account for reconciliation (Console → Team members → Invite) and leave two-factor auth (TOTP) off. An account with TOTP enabled must also submit a totp_code at login, which is unsuitable for scripts.

Rate limiting: the login endpoint is rate-limited per source IP. The correct pattern is "log in once → reuse the token for every pull" — do not re-login per request.

2.1 Login: POST /auth/login

TOKEN=$(curl -s https://portal.aiin1.ai/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{ "email": "billing-bot@yourcompany.com", "password": "YOUR_PASSWORD" }' \
  | jq -r .access_token)

Response:

{ "access_token": "eyJhbGci...", "token_type": "bearer", "expires_in": 900 }

Send Authorization: Bearer $TOKEN on all subsequent requests.

2.2 Usage aggregation: GET /obs/usage

Param Type Required Description
start / end date no Date range (YYYY-MM-DD, inclusive). Must be provided together, span ≤ 365 days, end must not be a future date. Falls back to range_days when omitted
range_days int no Last N days (default 7)
group string no Aggregation: date (default) / model / team / key / owner; comma-combine for a cross-tab (e.g. group=model,key) — group_key composes with | in the given order
model string no Filter by model name
apikey_id uuid no Filter by API key
team_id uuid no Filter by team
curl -s "https://portal.aiin1.ai/api/v1/obs/usage?start=2026-07-01&end=2026-07-31&group=model" \
  -H "Authorization: Bearer $TOKEN"

The response is an array; each row contains:

Field Description
group_key / group_name Aggregation key (date, model name, team / key ID and name)
request_count Request count
prompt_tokens / completion_tokens / total_tokens Input / output / total tokens
cache_creation_input_tokens / cache_read_input_tokens Cache write / hit tokens
cost_usd Spend (USD)
avg_latency_ms / error_count Average latency / error count

2.3 Per-request detail export: GET /obs/usage/export (CSV)

Params: start, end (required), optional model / apikey_id / team_id filters. Streams CSV directly:

curl -s "https://portal.aiin1.ai/api/v1/obs/usage/export?start=2026-07-01&end=2026-07-31" \
  -H "Authorization: Bearer $TOKEN" -o usage-202607.csv

CSV columns: occurred_at, request_id, trace_id, model, apikey_id, team_id, subscription_id, prompt_tokens, completion_tokens, cache_creation_input_tokens, cache_read_input_tokens, total_tokens, latency_ms, status_code, error_code, input_per_1m_usd, output_per_1m_usd, cache_write_per_1m_usd, cache_read_per_1m_usd, price_multiplier, cost_usd

One row per request: token facts plus the unit prices and discount in effect for that request (*_per_1m_usd are list prices, price_multiplier is your discount factor), so you can independently recompute cost_usd. Time columns are rendered in the organization's timezone.

Excel variants at the same path: GET /obs/usage/export.xlsx (details) and GET /obs/usage/stats.xlsx (statistics), same params.

2.4 Ledger & invoices

Endpoint Description
GET /billing/account Account snapshot: billing_mode, credit_balance_usd, credit_limit_usd
GET /billing/ledger?page=1&page_size=100 Ledger entries (top-ups / charges / adjustments): type, direction, amount_usd, balance_after_usd, description, created_at
GET /billing/invoices?start=&end=&page=&page_size= Invoice list: invoice_no, period_start/end, total, status, due_date
GET /billing/invoices/{id} Invoice detail (with line items)
GET /billing/invoices/{id}/pdf Invoice PDF download

2.5 Full example: daily T+1 reconciliation script

#!/usr/bin/env bash
set -euo pipefail
BASE="https://portal.aiin1.ai/api/v1"
DAY=$(date -d "yesterday" +%F 2>/dev/null || date -v-1d +%F)
 
TOKEN=$(curl -sf "$BASE/auth/login" -H "Content-Type: application/json" \
  -d "{\"email\":\"$BILLING_EMAIL\",\"password\":\"$BILLING_PASSWORD\"}" | jq -r .access_token)
 
# Yesterday's per-request detail CSV
curl -sf "$BASE/obs/usage/export?start=$DAY&end=$DAY" \
  -H "Authorization: Bearer $TOKEN" -o "usage-$DAY.csv"
 
# Yesterday's per-model summary
curl -sf "$BASE/obs/usage?start=$DAY&end=$DAY&group=model" \
  -H "Authorization: Bearer $TOKEN" > "usage-$DAY-by-model.json"
 
# Current balance (token channel; also fits a standalone balance-alert job)
curl -sf https://api.portal.aiin1.ai/v1/dashboard/billing/credit_grants \
  -H "Authorization: Bearer $NEXARA_API_KEY" > "balance-$DAY.json"

3. FAQ

Q: Can the two channels disagree? No. The balance channel's month-to-date spend and the sum of per-request cost_usd from the detail channel come from the same ledger. The only thing to watch is the timezone: month boundaries and detail timestamps follow your organization's timezone — use the same timezone when aggregating on your side.

Q: What if the access_token expires? It lives for 15 minutes by design — a reconciliation script should "log in → pull → done". If a single pull exceeds 15 minutes (a very large export), split the date range into batches.

Q: Can I pull line-item details with the sk-nex- token directly? The detail channel currently requires account login. If your use case strongly needs token-based detail queries, contact us.