Pricing, usage, and balance
Use three read-only, buyer-scoped endpoints to read the prices that apply to your account, reconcile finalized charges, and check current service-credit headroom.
Availability
Enabled per customer account
Credential
Dedicated bi_v1_ credential
Scope
Authenticated buyer only
Currency
USD decimal strings
Before you call
Billing Integration is separate from model inference. Your account must be enabled and you must use the dedicated reporting credential supplied during onboarding.
API_ORIGIN="https://api.elss.ai"
BILLING_CREDENTIAL="replace-with-your-bi_v1-credential"- Send the credential in Authorization: Bearer. A normal sk-* inference key is rejected.
- Keep the credential on a trusted server. Do not place it in browser code, mobile apps, repositories, URLs, or logs.
- The credential is fixed to your buyer account and billing.read scope. The API does not accept account_id or another customer selector.
- All successful responses are JSON and include Cache-Control: private, no-store. Monetary values are exact decimal strings, never binary floating-point numbers.
Recommended polling flow
Each endpoint answers a different accounting question. Keep their responsibilities separate in your integration.
1. Cache the price contract
Read /pricing and retain catalog_revision with ETag.
2. Import finalized usage
Poll a closed UTC settlement window and store its immutable revision references.
3. Monitor headroom
Read /balance for the amount currently available to spend.
/v1/billing/pricing
Returns the active customer-visible catalog, or one exact historical catalog revision, for the authenticated buyer.
Request contract
| Field | Type / location | Requirement | Meaning |
|---|---|---|---|
Authorization | header · string | Required | Bearer followed by the dedicated bi_v1_ credential. |
model | query · string | Optional | Return one exact canonical model. An unknown model returns billing_catalog_not_found. |
catalog_revision | query · string | Optional | Read one immutable historical catalog. Omit it for the active catalog. |
If-None-Match | header · string | Optional | Send the ETag from a prior response. An exact match returns 304 with no body. |
Example request
curl --get "$API_ORIGIN/v1/billing/pricing" \
--data-urlencode "model=gpt-5.4" \
--header "Authorization: Bearer $BILLING_CREDENTIAL"Example response
{
"catalog_revision": "9e0d...5b7a",
"effective_at": "2026-08-18T00:00:00Z",
"settlement_profile_revision": "5c81...b210",
"currency": "USD",
"items": [
{
"model": "gpt-5.4",
"catalog_item_revision": "861a...0d4c",
"commitment_label": "Standard service",
"rates": [
{
"component": "input",
"unit": "token",
"variant": "standard",
"min_input_tokens": 0,
"state": "priced",
"amount": "2.500000000",
"unit_scale": 1000000
}
]
}
]
}Response contract
| Field | Type / location | Requirement | Meaning |
|---|---|---|---|
catalog_revision | string | Always | Opaque revision for the complete customer-visible catalog. |
effective_at | RFC3339 UTC | Always | Time this catalog revision became active. |
settlement_profile_revision | string | Always | Immutable revision used to convert internal quota into public USD amounts. |
currency | string | Always | USD in Billing Integration v1. |
items[].model | string | Always | Canonical model ID callable by this buyer. |
items[].catalog_item_revision | string | Always | Opaque price revision for this model item. |
items[].commitment_label | string | When present | Customer-visible service commitment label. |
items[].rates[] | array | Always | Component rates keyed by component, unit, variant, and minimum input-token band. |
rates[].amount | decimal string | Always | USD price for the entire rates[].unit_scale quantity, not for one unit. |
rates[].state | priced | free | Always | Whether this component has a positive price or is explicitly free. |
How to use the result
- Persist catalog_revision and catalog_item_revision beside any downstream cost rule derived from this response.
- Treat each rate as amount per unit_scale. Use a decimal library and preserve every returned fractional digit.
- Use the greatest applicable min_input_tokens band for the returned variant; do not average multiple bands.
- Cache by ETag, but refetch the active catalog before changing production pricing assumptions.
/v1/billing/usage
Returns a complete aggregate of finalized billing records for one closed UTC settlement window.
Request contract
| Field | Type / location | Requirement | Meaning |
|---|---|---|---|
Authorization | header · string | Required | Bearer followed by the dedicated bi_v1_ credential. |
start_time | query · RFC3339 UTC | Required | Inclusive start, whole-second timestamp ending in Z. |
end_time | query · RFC3339 UTC | Required | Exclusive end, whole-second timestamp ending in Z. It cannot be in the future. |
group_by | query · string | Required | Must be exactly model in v1. |
Example request
curl --get "$API_ORIGIN/v1/billing/usage" \
--data-urlencode "start_time=2026-08-17T00:00:00Z" \
--data-urlencode "end_time=2026-08-18T00:00:00Z" \
--data-urlencode "group_by=model" \
--header "Authorization: Bearer $BILLING_CREDENTIAL"Example response
{
"start_time": "2026-08-17T00:00:00Z",
"end_time": "2026-08-18T00:00:00Z",
"as_of": "2026-08-18T00:05:00Z",
"data_complete_through": "2026-08-18T00:00:00Z",
"items": [
{
"model": "gpt-5.4",
"catalog_revision": "9e0d...5b7a",
"catalog_item_revision": "861a...0d4c",
"settlement_profile_revision": "5c81...b210",
"currency": "USD",
"meters": [
{
"code": "input",
"quantity": "4200000",
"unit": "token",
"coverage": "complete",
"evidence_state": "final"
}
],
"request_count": 128,
"gross_amount": "12.000000000",
"waiver_amount": "2.000000000",
"net_billed_amount": "10.000000000",
"charge_state": "waived",
"coverage": "complete",
"data_complete_through": "2026-08-18T00:00:00Z",
"as_of": "2026-08-18T00:05:00Z"
}
]
}Response contract
| Field | Type / location | Requirement | Meaning |
|---|---|---|---|
start_time / end_time | RFC3339 UTC | Always | Echoed half-open settlement window [start_time, end_time). |
as_of | RFC3339 UTC | Always | Server snapshot time for this report. |
data_complete_through | RFC3339 UTC | Always | Completeness boundary. On success it matches the requested end_time. |
items[].model | string | Always | Canonical model ID. |
items[].catalog_revision | string | Always | Catalog revision active for these settled records. |
items[].catalog_item_revision | string | Always | Exact model-price revision used for these records. |
items[].settlement_profile_revision | string | Always | USD conversion revision used for all amounts in this row. |
items[].meters[] | array | Always | Final measured quantities. Each entry includes code, quantity, unit, coverage, and evidence_state. |
items[].request_count | integer | Always | Logical customer requests, not provider attempts or retries. |
gross_amount | decimal string | Always | Charge before waivers. |
waiver_amount | decimal string | Always | Waived amount, including exact display-rounding conservation where applicable. |
net_billed_amount | decimal string | Always | Authoritative customer charge. gross_amount - waiver_amount equals this value exactly. |
charge_state | charged | waived | no_charge | Always | Why this aggregate has its reported net amount. |
coverage | complete | Always | Evidence completeness for this aggregate. Incomplete reports fail instead of returning partial rows. |
How to use the result
- The window is based on billing_settled_at, not request creation time. Query a closed UTC period such as the previous day.
- The maximum window is 31 days and the maximum result is 1,000 aggregate rows. Split large reconciliation jobs into smaller windows.
- Rows are separated when model, catalog revision, item revision, settlement profile, or charge state differs. Do not merge them without preserving those dimensions.
- Only ingest a 200 response. A billing_report_not_ready error means the entire window is unavailable; no partial result was returned.
- Parse quantities and money as decimal strings. Do not use IEEE-754 float arithmetic for reconciliation.
/v1/billing/balance
Returns the authenticated buyer's current service-credit and admission-credit headroom.
Request contract
This endpoint accepts no query parameters.
| Field | Type / location | Requirement | Meaning |
|---|---|---|---|
Authorization | header · string | Required | Bearer followed by the dedicated bi_v1_ credential. |
Example request
curl "$API_ORIGIN/v1/billing/balance" \
--header "Authorization: Bearer $BILLING_CREDENTIAL"Example response
{
"currency": "USD",
"balance_kind": "service_credit",
"available_service_credit": "4820.150000000",
"admission_credit": "500.000000000",
"available_to_spend": "5320.150000000",
"settlement_profile_revision": "5c81...b210",
"as_of": "2026-08-18T09:00:00Z"
}Response contract
| Field | Type / location | Requirement | Meaning |
|---|---|---|---|
currency | string | Always | USD in Billing Integration v1. |
balance_kind | service_credit | Always | Confirms that the response is service capacity, not cash or a refundable wallet. |
available_service_credit | decimal string | Always | Non-negative prepaid or account service-credit component. |
admission_credit | decimal string | Always | Non-negative credit-line component used for request admission. |
available_to_spend | decimal string | Always | Authoritative current spendable headroom after account deficit rules. |
settlement_profile_revision | string | Always | USD conversion revision used by this snapshot. |
as_of | RFC3339 UTC | Always | Server time at which the balance was read. |
How to use the result
- Use available_to_spend as the alert and admission value. It may differ from adding the two displayed components when the account carries a deficit.
- Do not present these values as cash, funds on deposit, refundable balance, or an accounting ledger balance.
- A successful read does not reserve capacity. Recheck close to any consequential operation and tolerate concurrent spending.
Errors and recovery
Billing endpoint errors use a stable JSON envelope with code, message, and request_id. Branch on error.code; preserve request_id for support.
| HTTP | Error code | Meaning | Client action |
|---|---|---|---|
| 400 | billing_request_invalid | Unknown field, invalid timestamp, unsupported grouping, or invalid window. | Correct the request; do not retry unchanged. |
| 400 | billing_result_limit_exceeded | The report would exceed the bounded aggregate result limit. | Split the time range into smaller windows. |
| 401 | billing_credential_invalid | Credential is missing, malformed, expired, revoked, or no longer valid for the active account profile. | Replace or rotate the credential; do not use an sk-* key. |
| 404 | billing_integration_unavailable | The optional Billing Integration capability is not ready on this deployment. | Verify service availability or contact support; avoid rapid retries. |
| 404 | billing_catalog_not_found | The requested model or historical catalog revision is unavailable. | Fetch the active catalog or correct the selector. |
| 409 | billing_report_not_ready | One or more required settlement or evidence facts are not complete for the requested window. | Do not ingest partial data; retry the same window with backoff. |
| 503 | billing_query_timed_out | The bounded reporting query exceeded its server deadline. | Retry with backoff; use a smaller window if it repeats. |
| 500 | billing_query_failed | An unexpected reporting failure occurred. | Retry with backoff and provide request_id if it persists. |
Billing error envelope
{
"error": {
"code": "billing_report_not_ready",
"message": "Billing report is not ready.",
"request_id": "req_01J..."
}
}Retry policy
- GET requests are idempotent. Retry 409, 429, 500, and 503 with exponential backoff and jitter; cap attempts and surface persistent failures.
- Do not automatically retry 400 or 401 without changing the request or credential. Treat 404 as a configuration or selector issue first.
- A gateway rate limit can return HTTP 429 using the standard API error envelope instead of the billing-specific code envelope.
- Log status, error.code, and request_id. Never log the Authorization header or raw credential.
Go-live checklist
Complete these checks before relying on the API for customer-facing accounting or automated controls.
- Store the bi_v1_ credential in a server-side secret manager and verify that sk-* keys are not used on billing routes.
- Use an exact decimal library for every amount and meter quantity.
- Persist catalog, catalog-item, and settlement-profile revisions with imported usage.
- Poll closed UTC windows, preserve [start_time, end_time), and make imports idempotent by window plus returned revisions.
- Treat 409 as no report, not zero usage, and alert after bounded retries.
- Use available_to_spend for headroom monitoring while treating the response as a non-reserving snapshot.