# v1: account

> Balance, task types and prices, key information and usage reports in the Noptcha v1 API.

Source: https://noptcha.com/docs/native-api/account/

## Balance

`GET /v1/balance` (scope `balance:read`):

**curl**

```bash
export NOPTCHA_KEY=nop_test_...  # your test or live key
curl -s "https://api.noptcha.com/v1/balance" \
  -H "Authorization: Bearer $NOPTCHA_KEY"
```


**Python**

```python
import os

import requests

API = "https://api.noptcha.com"
KEY = os.environ["NOPTCHA_KEY"]

r = requests.get(
    f"{API}/v1/balance",
    headers={
        "Authorization": f"Bearer {KEY}",
    },
    timeout=30,
)
print(r.status_code, r.json())
```


**Node.js**

```js
const API = 'https://api.noptcha.com';
const KEY = process.env.NOPTCHA_KEY;

const res = await fetch(`${API}/v1/balance`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${KEY}`,
  },
});
console.log(res.status, await res.json());
```

| Field | Meaning |
| --- | --- |
| `available` | What new tasks can use: `cash` + `promo` + `credit_limit` − `held` |
| `cash` | Money you paid in |
| `promo` | Promotional credit |
| `held` | Reserved for tasks in flight |
| `credit_limit` | Credit agreed with us separately; zero unless you have such an agreement (accounts are prepaid by default) |

All amounts are decimal strings with 6 places; `currency` is `USD`.

## Task types and prices

`GET /v1/types` returns the types your organization can use, with their deadline, variants and the price of each variant for your organization. Any valid key can call it.

**curl**

```bash
export NOPTCHA_KEY=nop_test_...  # your test or live key
curl -s "https://api.noptcha.com/v1/types" \
  -H "Authorization: Bearer $NOPTCHA_KEY"
```


**Python**

```python
import os

import requests

API = "https://api.noptcha.com"
KEY = os.environ["NOPTCHA_KEY"]

r = requests.get(
    f"{API}/v1/types",
    headers={
        "Authorization": f"Bearer {KEY}",
    },
    timeout=30,
)
print(r.status_code, r.json())
```


**Node.js**

```js
const API = 'https://api.noptcha.com';
const KEY = process.env.NOPTCHA_KEY;

const res = await fetch(`${API}/v1/types`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${KEY}`,
  },
});
console.log(res.status, await res.json());
```

`data` is an empty list when no type is available. `price_version` identifies the price list the prices come from.

### Public catalog

`GET /v1/catalog` lists every public task type with its list price, in the same shape, and needs no key (a key sent along is ignored). It is meant for price tables and for tools that have no key yet; use `GET /v1/types` for the prices that apply to your organization.

```sh
curl https://api.noptcha.com/v1/catalog
```

The response also has `currency` (`USD`) and `placeholder` (`true` only on test deployments, where the prices are not real). It may be cached for 5 minutes (`Cache-Control: public, max-age=300`) and carries an `ETag`: send it back in `If-None-Match` to get `304 Not Modified`. Any website may read it from the browser (`Access-Control-Allow-Origin: *`, on error responses too). There is no CORS preflight: send a simple request (a plain `fetch(url)`, or only safelisted headers such as `Accept`); a request with `Authorization` or another custom header is blocked by the browser. The rate limit is per client IP (IPv6: per /64, and per /48 at ten times the rate), see [Limits](https://noptcha.com/docs/limits.md). Requests are limited per client IP: 60 per minute, bursts of 30 (starting values); beyond that `429 rate_limited` with `Retry-After`.

## The key itself

`GET /v1/me` shows the organization, the key (prefix and last four characters, mode, scopes, allowed types and IP ranges, expiry), its budget and how much of it is used in the current period, and the rate limits that apply. Any valid key can call it; it never returns the key itself.

**curl**

```bash
export NOPTCHA_KEY=nop_test_...  # your test or live key
curl -s "https://api.noptcha.com/v1/me" \
  -H "Authorization: Bearer $NOPTCHA_KEY"
```


**Python**

```python
import os

import requests

API = "https://api.noptcha.com"
KEY = os.environ["NOPTCHA_KEY"]

r = requests.get(
    f"{API}/v1/me",
    headers={
        "Authorization": f"Bearer {KEY}",
    },
    timeout=30,
)
print(r.status_code, r.json())
```


**Node.js**

```js
const API = 'https://api.noptcha.com';
const KEY = process.env.NOPTCHA_KEY;

const res = await fetch(`${API}/v1/me`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${KEY}`,
  },
});
console.log(res.status, await res.json());
```

For test keys `limits.sandbox` shows the [sandbox limits](https://noptcha.com/docs/sandbox.md#limits) and the budget’s `used` is always zero.

## Usage

`GET /v1/usage` (scope `usage:read`) reports solved (billed) and unbilled tasks and the amounts charged, by hour or day and by type or key:

**curl**

```bash
export NOPTCHA_KEY=nop_test_...  # your test or live key
curl -s "https://api.noptcha.com/v1/usage?granularity=day&group_by=type" \
  -H "Authorization: Bearer $NOPTCHA_KEY"
```


**Python**

```python
import os

import requests

API = "https://api.noptcha.com"
KEY = os.environ["NOPTCHA_KEY"]

r = requests.get(
    f"{API}/v1/usage",
    params={
        "granularity": "day",
        "group_by": "type",
    },
    headers={
        "Authorization": f"Bearer {KEY}",
    },
    timeout=30,
)
print(r.status_code, r.json())
```


**Node.js**

```js
const API = 'https://api.noptcha.com';
const KEY = process.env.NOPTCHA_KEY;

const res = await fetch(`${API}/v1/usage?granularity=day&group_by=type`, {
  method: 'GET',
  headers: {
    Authorization: `Bearer ${KEY}`,
  },
});
console.log(res.status, await res.json());
```

| Parameter | Values | Default |
| --- | --- | --- |
| `granularity` | `hour`, `day` | `day` |
| `group_by` | `type`, `key` | `type` |
| `from`, `to` | RFC 3339 or `YYYY-MM-DD`, UTC; `to` is exclusive | the last 24 hours (`hour`) or 30 days (`day`) |

-   Ranges are rounded to whole hours or days. At most 7 days by hour and 92 days by day; `group_by=key` covers only the last 90 days (an earlier `from` is moved forward, and the response’s `from` shows the effective start).
-   At most 10,000 rows; a larger request is `400 invalid_request` (narrow the range or use days).
-   Amounts are what was actually deducted from your balance, including corrections. `data` lists only periods with activity; `totals` sums them. With `group_by=key`, a row with `"key": null` holds any amount not attributed to a key (usually zero).
-   Limited to 20 requests per minute per organization (bursts of 5), with `RateLimit-Policy` and `RateLimit` headers.
-   Test keys get an empty report with `"sandbox": true`.

These ranges and limits are starting values and may change.
