Account and catalog API

GET /v1/models, GET /v1/usage, and the public GET /api/v1/models/pricing: authentication, example responses, field types and units, and the response headers HopBase sets.

Three read-only endpoints tell your code which models a key can call, how much the key can still spend, and what every model costs at list price. None of them is billed, and none needs a positive balance.

EndpointAuthenticationWhat it returns
GET /v1/modelsKey: Authorization: Bearer sk-… or x-api-key: sk-…The models this key's group serves
GET /v1/usageKey: Authorization: Bearer sk-… onlyWhat this key can still spend, and its quota
GET /api/v1/models/pricingNoneThe public model catalog with list prices

List models

curl https://api.hop-base.com/v1/models \
  -H "Authorization: Bearer sk-your-key"

The list contains only the models of the group the key is bound to, and it comes back complete in one response (no paging). Keys from OpenAI-compatible groups get an OpenAI-shaped list:

{
  "object": "list",
  "data": [
    {
      "id": "gpt-6-astra",
      "object": "model",
      "created": 1790222400,
      "owned_by": "hopbase",
      "capabilities": ["chat", "reasoning"],
      "context_window": 1050000,
      "context_length": 1050000,
      "max_input_tokens": 1050000,
      "max_output_tokens": 128000
    }
  ]
}

Keys from Claude groups get the Anthropic shape:

{
  "object": "list",
  "data": [
    {
      "id": "claude-opus-5-5",
      "object": "model",
      "type": "model",
      "display_name": "Claude Opus 5.5",
      "created_at": "2026-09-22T00:00:00Z"
    }
  ],
  "has_more": false,
  "first_id": "claude-opus-5-5",
  "last_id": "claude-haiku-4-5-20251001"
}
FieldTypeMeaning
data[].idstringThe model ID to send in requests. This is the only field to rely on
data[].capabilitiesstring[]For example chat, reasoning, image_generation
data[].image_onlybooleantrue for image models; absent otherwise
data[].context_window, context_length, max_input_tokensinteger, tokensSame value in three spellings for client compatibility; absent when not published
data[].max_output_tokensinteger, tokensAbsent when not published
data[].createdinteger, Unix secondsTime of this response, not a release date
data[].display_name, created_atstringClaude groups only; created_at is the model's release date (RFC 3339)

has_more, first_id and last_id are there for SDK compatibility only: the list is never paged, so do not page with them. Fields other than id can be missing for some models; treat unknown fields as optional.

Balance and quota

curl https://api.hop-base.com/v1/usage \
  -H "Authorization: Bearer sk-your-key"
{
  "is_active": true,
  "balance": 125.4,
  "remaining": 125.4,
  "unit": "USD",
  "quota": {
    "remaining": 125.4,
    "api_key_remaining": 125.4,
    "total": 0,
    "used": 3.12,
    "unlimited": true
  }
}
FieldTypeMeaning
balancenumberWhat this key can spend right now. Key without its own quota: the account balance. Key with a quota: the quota left on the key. Keys of team members and departments are further capped by the member's and department's remaining quota for the period
remainingnumberSame value as balance
is_activebooleantrue when balance is above 0
unitstringAlways "USD". It does not tell you the currency; see the note below
quota.remainingnumberSame value as balance
quota.api_key_remainingnumberQuota left on this key; equals the account balance when the key has no quota
quota.totalnumberThe key's quota; 0 means no key quota
quota.usednumberTotal charged to this key so far
quota.unlimitedbooleantrue when the key has no quota of its own

Amounts are in your balance currency

All amounts are in the currency your account balance is kept in — the same numbers the console shows for your balance and in Usage. Do not read the currency from unit.

A key with its own quota still draws on the account balance: when the account runs out first, requests return 402 even though balance here shows quota left.

This endpoint does not use the standard error body. Failures look like this:

CaseStatusBody
No key, or not an sk- key401{"is_active": false, "balance": 0, "message": "missing or invalid api key"}
Unknown or disabled key401"message": "invalid api key"
Expired key200"is_active": false, "message": "api key expired"
Team member disabled200"is_active": false, "message": "member disabled"

Branch on is_active, not only on the HTTP status. For itemised charges, open Usage in the console.

Public model catalog

curl https://api.hop-base.com/api/v1/models/pricing

No key needed. The response allows cross-origin requests from any site and may be cached for up to 5 minutes (Cache-Control: public, max-age=300). Prices are the list prices in USD before your group's rate; what you actually pay per model is shown in the signed-in model catalog.

{
  "code": 0,
  "message": "ok",
  "data": [
    {
      "platform": "openai",
      "models": [
        {
          "id": "gpt-6-astra",
          "name": "GPT-6 Astra",
          "context_window": 1050000,
          "capabilities": ["chat", "reasoning"],
          "vendor": "openai",
          "category": "chat",
          "input": 10,
          "cached_input": 1,
          "output": 50,
          "long_context": {
            "threshold": 272000,
            "input_multiplier": 2,
            "cached_multiplier": 2,
            "output_multiplier": 1.5
          },
          "price_unit": "token"
        }
      ]
    },
    {
      "platform": "minimax",
      "models": [
        {
          "id": "speech-2.8-hd",
          "name": "MiniMax Speech 2.8 HD",
          "capabilities": ["tts"],
          "vendor": "minimax",
          "series": "minimax-speech",
          "category": "audio",
          "input": 100,
          "output": 0,
          "price_unit": "character"
        }
      ]
    }
  ]
}
FieldTypeMeaning
codeinteger0 on success
data[].platformstringThe integration family the model is served through (for example openai, claude, gemini, kling). It is not the model maker — see vendor
models[].idstringModel ID to send
models[].namestringDisplay name
models[].vendorstringModel maker, for example openai, google; may be absent
models[].seriesstringFamily used to group versions in the console; may be absent
models[].categorystringchat, image, video, audio, or embedding
models[].capabilitiesstring[]For example chat, reasoning, image_generation, image_edit, video_generation, tts
models[].context_windowinteger, tokensAbsent when not published
models[].price_unitstringUnit of every price on the entry: token = per 1M tokens, second = per second of video, image = per image, character = per 1M billed characters
models[].input, cached_input, outputnumber, USD per price_unitcached_input is absent when caching does not apply. Speech models use input only
models[].long_contextobjectPresent when a long-context tier exists: above threshold input tokens the whole request is billed at input_multiplier / cached_multiplier / output_multiplier
models[].imageobjectPer-image price by resolution tier, for example {"1k": …, "2k": …, "4k": …}
models[].video_tokensobjectVideo price per bucket (resolution, audio, reference media). The unit follows price_unit: per 1M video tokens for token, per second for second. The key name is historical

A model can appear under more than one platform when it is offered through more than one group. New fields may be added; ignore fields you do not recognize.

Response headers

HeaderSent onMeaning
x-request-idEvery responseID of this request. Include it when you report a problem
Retry-After429 from the concurrency cap; 429 and 503 when a wait time is knownSeconds to wait before retrying
Retry-After-Ms429 from the concurrency cap, and other 429s with a known waitThe same wait in milliseconds

HopBase does not send headers with your concurrency cap, requests in flight, or remaining balance. Use GET /v1/usage for the balance, and see Concurrency, timeouts, and billing for the caps. Some model responses carry their own rate-limit headers (x-ratelimit-*, anthropic-ratelimit-*); they do not describe your account's or key's limits, so do not throttle on them.

On this page