API Reference

Get current API key

Describes the key that made the request — there is nothing to name and no identifier to pass, so a key can only ever read itself.

GET/api/v1/key

The reply is the state of the bearer token in the header: how much the account behind it has spent, over which windows, what ceiling it carries and how much can still be spent right now. It is the route to poll when you want to see a refusal coming rather than collect it.

No parameters

No path segment, no query string, no body — the header is the whole request. The route needs no balance and is not charged, so it is safe to call on a schedule.

shell
curl https://api.gtokens.io/api/v1/key \
  -H "Authorization: Bearer sk-sl-your-key"

Response

200 with a single data object. All nine fields are always present, so no key has to be tested for; limit and limit_reset are null on an account with no ceiling, which is the usual case. Every amount is in US dollars and arrives as a plain JSON number, never as a string.

Fields of the data object
FieldTypeDescription
labelstringThe key, shortened: the sk-sl- prefix and the first eight characters of it, then an ellipsis. Enough to tell two keys apart in a log, not enough to authenticate with.
usagenumberEverything THIS KEY has been charged over its whole life. No window, and it never goes back down. For the account as a whole, call /credits instead.
usage_dailynumberCharged on this key since midnight today, in the account’s time zone.
usage_weeklynumberCharged on this key since midnight on Monday of the current week.
usage_monthlynumberCharged on this key since midnight on the first day of the current month.
limitnumber | nullThis key’s own spending ceiling, or the account ceiling when the key has none of its own — and null when there is neither.
limit_remainingnumberHow much can be spent right now: the smallest of the prepaid balance, what is left of this key’s ceiling, and what is left of the account’s daily and monthly ones. It can be smaller than limit minus usage — that means another ceiling is closer.
limit_resetstring | nullWhich window the ceiling covers: daily, weekly or monthly. Null means the ceiling has no window — it covers the whole life of the key — or that there is no ceiling at all.
is_free_tierbooleanAlways false. There is no free allowance here, and no state in which one appears.

Scroll the table sideways for the description.

Spend windows

The three windowed counters are calendar windows in the account’s own time zone: the day starts at midnight, the week on Monday, the month on the first, and each returns to zero at its own boundary. The zone is the one the dashboard reports from the browser, so these counters agree with what a person sees there; an account that has never opened the dashboard stays on UTC. usage has no boundary at all and is the lifetime figure.

A calendar boundary, not the last 24 hours

An hour after midnight usage_daily reports one hour of work, not yesterday evening plus one hour. The difference is the whole point of the field: a trailing window would disagree with your own daily report by exactly the previous evening, every single day, and the busier the evening the wider the gap. If you need a trailing figure, keep it yourself — these counters cannot produce one.

Counters are built from what was actually charged for finished requests, which is the same figure the request log and the account area show. A call still in flight is not in them yet.

Limit and remaining

limit is this key’s own ceiling, and limit_reset names the window it covers — without the second field the first says nothing, because a hundred dollars a day and a hundred a month are different products. A key with no ceiling of its own falls back to the account ceiling; when there is neither, both fields are null and the prepaid balance is the only bound.

limit_remaining answers one question — how much can be spent right now — and it is the smallest of everything that can stop the next request: the balance, what is left of this key’s ceiling, and what is left of the account’s daily and monthly ones. Reading it as limit minus usage is the one mistake to avoid: the figure can be smaller because another ceiling is closer, and on an account whose balance runs out first it is the balance, moving with every top-up.

A snapshot, not a reservation
  • Every key on the account draws on the same balance, so a figure read here can be spent by another key a second later — even one with a ceiling of its own, because ceilings bound spending, they do not reserve it.
  • A request in flight has already put its estimated cost aside against the balance, so limit_remaining drops when the call starts, while the usage counters only move when it finishes and the exact amount is known. The two sides of the object disagree for the length of a call, and that is normal.
  • The ceiling that refuses a request is measured over the same calendar window this object reports, so the two agree at a boundary as well as in the middle of a day. Plan with the figure — and still handle 402, because another key on the account can spend the same money first.

is_free_tier is always false. Every request is paid from the prepaid balance, and one the balance cannot cover comes back 402 payment_required without being served — there is no free allowance to fall back to and none to wait for.

Example response

200 application/json
{
  "data": {
    "label": "sk-sl-9tKq2Xa4...",
    "usage": 412.905311,
    "usage_daily": 4.10322,
    "usage_weekly": 31.884004,
    "usage_monthly": 128.443121,
    "limit": 100.0,
    "limit_remaining": 95.89678,
    "limit_reset": "daily",
    "is_free_tier": false
  }
}

This account has a daily ceiling of 100 and has used a little over four of it since midnight, so limit_remaining is what the ceiling still allows today. Its balance is larger than that; had it been smaller, the balance would be the number shown instead.

Watching the quota

A batch that starts with two dollars left does not stop politely. It stops in the middle, with part of the work done and paid for and the rest returning refusals, and the operator finds out from the failures rather than from a number. Reading limit_remaining before a run, or on a schedule, turns that into a decision made in advance.

guard.py
import requests

r = requests.get(
    "https://api.gtokens.io/api/v1/key",
    headers={"Authorization": "Bearer sk-sl-your-key"},
    timeout=30,
)
r.raise_for_status()
data = r.json()["data"]

# Stop before the gateway has to. Pick the floor from your own run:
# the number of calls ahead times the catalogue rate for what you ask for.
if data["limit_remaining"] < 25:
    raise SystemExit(f"only {data['limit_remaining']:.2f} USD left, top up first")

print(f"spent today: {data['usage_daily']:.2f} USD")
guard.ts
const r = await fetch('https://api.gtokens.io/api/v1/key', {
  headers: { Authorization: 'Bearer sk-sl-your-key' },
})
if (!r.ok) throw new Error(`key check failed: ${r.status}`)

const { data } = await r.json()

// Cheap enough to run from a scheduler: no model is touched
// and the call itself is not charged.
if (data.limit_remaining < 25) {
  throw new Error(`only ${data.limit_remaining.toFixed(2)} USD left`)
}

Polling costs nothing, but it is not invisible: a call counts as a use of the key, so the last-used time on the keys screen moves — at most once every five minutes, however often you ask.

Errors

Error responses of this route
StatusTyped codeWhen
401authenticationNo Authorization header, a header that is not a bearer token, or a key that is unknown or has been revoked.
403permission_deniedThe key is valid but the account is suspended. No other route answers either, so this is the cheapest way to see it.
500serverOur failure, not the request. The body carries no detail beyond the code; retry, and tell support if it keeps happening.

Scroll the table horizontally for the last column.

Errors arrive in the same envelope on every route: a numeric code, a human message, and metadata.error_type to branch on — branching on the HTTP status alone loses the difference between causes that share one.

401 application/json
{
  "error": {
    "code": 401,
    "message": "invalid api key",
    "metadata": {
      "error_type": "authentication",
      "reason": "invalid_credentials"
    }
  }
}
Every status and typed code
Authorization

A bearer token in the Authorization header, the same as on every other route: Authorization: Bearer sk-sl-…. The x-api-key header is not read anywhere.

How keys are issued and revoked