# Credits API

> GET /v1/credits returns the organization balance, and the spend and budgets of the key you call with.


Read your balance without spending anything. The call is free and holds nothing.

```endpoint
GET https://api.notholy.com/v1/credits
```

```bash test
curl https://api.notholy.com/v1/credits -H "Authorization: Bearer $NOTHOLY_API_KEY"
```

## Response

```json
{
  "object": "credits",
  "currency": "USD",
  "balance": "24.913402",
  "reserved": "0.004000",
  "available": "24.909402",
  "key": { "spent": "0.086598", "daily_budget": "5.000000" }
}
```

| Field | Type | Notes |
|---|---|---|
| `object` | string | Always `credits` |
| `currency` | string | Always `USD` |
| `balance` | string | Credits minus usage already charged |
| `reserved` | string | Held right now by requests in flight. Each hold is the worst-case cost of its request; the unused part returns when it settles |
| `available` | string | What a new request can reserve: `balance` minus `reserved` |
| `key.spent` | string | Total spent with this key |
| `key.total_budget`, `key.daily_budget` | string | Present when the key has budgets |

Amounts are decimal strings with 6 decimal places. Inside NotHoly they are integers in billionths of a dollar, so no rounding happens between requests.

> [!NOTE]
> Every request reserves its worst case (prompt plus `max_tokens`) before it starts. When `available` is lower than that, the output limit shrinks to fit, and below 16 tokens the request returns `402 insufficient_credits`. Check `available` before long generations.

```js test
const r = await fetch('https://api.notholy.com/v1/credits', { headers: { Authorization: `Bearer ${process.env.NOTHOLY_API_KEY}` } });
const c = await r.json();
console.log(c.available);
```

## Errors

| Status | Code | Meaning |
|---|---|---|
| 401 | `invalid_api_key` | Missing, invalid, revoked or expired key |
| 500 | `internal_error` | The balance could not be read. Retry with backoff |
