# Кредити та ліміти

AstroWay використовує **кредитну модель** замість простого лічильника запитів.

<GetApiKeyBlock variant="compact" /> Це справедливіше: легкі ендпоінти (`/planets`) коштують 10 кредитів, важкі (`/rectification`) — 500.

## Два види лімітів

### 1. Денний/місячний бюджет кредитів

Кількість кредитів на місяць залежить від плану:

| План | Кредитів/міс | Денний ліміт |
|---|---|---|
| Free | 10 000 | ~333 |
| Indie | 50 000 | ~1 667 |
| Starter | 200 000 | ~6 667 |
| Pro | 800 000 | ~26 667 |
| Business | 3 500 000 | ~116 666 |
| Enterprise | Custom | Custom |

Щойно кредити вичерпано — наступні запити повертають `402 Payment Required` (Free) або запускають overage-білінг (Indie+).

### 2. Rate limit (requests per minute)

| План | RPM |
|---|---|
| Free | 10 req/min |
| Indie | 30 req/min |
| Starter | 120 req/min |
| Pro | 400 req/min |
| Business | 1 000 req/min |
| Enterprise | Custom |

Rate limit — sliding window. Якщо вистрілив 120 запитів за 10 секунд, наступні 50 секунд на цьому ключі — `429`.

<Aside type="tip">
Rate limit і credit budget — незалежні. Можна мати кредити, але не пройти rate limit. І навпаки.
</Aside>

### 3. Публічні ендпоінти (без ключа)

14 reference-словників `/v1/reference/*` (signs, planets, houses, aspects, elements, modalities, polarities, dignities, decans, nakshatras, lots, asteroids, zodiac-systems, glyphs) обслуговуються **публічно, без `X-Api-Key`** і коштують **0 кредитів**. Обмеження — 30 запитів / годину з одного IP. Ці ж дані виставлені як MCP Resources `astroway://reference/<slug>` для LLM-агентів.

## Таблиця вартості

**Повна прозора таблиця** з усіма {siteMeta.endpoints}+ ендпоінтами і їх вартістю — на сторінці [Вартість ендпоінтів](/credits/). DivineAPI/AstrologyAPI/Prokerala такої таблиці не публікують. Короткий орієнтир:

| Tier | Кредитів | Типовий час | Приклади |
|---|---|---|---|
| 1 | 10 | < 50 мс | `/planets`, `/moon-voc`, `/iching` |
| 2 | 20 | 50–200 мс | `/chart`, `/harmonics`, `/horary` |
| 3 | 50 | 200–500 мс | `/synastry`, `/progressions`, `/acg` |
| 4 | 100 | > 500 мс | `/transit-calendar`, `/forecast-calendar` |
| 5 | 250 | кілька с | `/rectification/trutine` |
| 6 | 500 | до 120 с | `/rectification` |

## Заголовки відповіді

Кожна відповідь містить:

```http
X-Credits-Used: 20
X-Credits-Remaining: 9980
X-Credits-Limit: 10000
X-Credits-Reset: 2026-05-01T00:00:00Z
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 118
X-RateLimit-Reset: 1714521600
X-Request-Id: 01HXY2A7ZM...
```

- `X-Credits-Used` — скільки списано за цей запит
- `X-Credits-Remaining` — залишок на місячному бюджеті
- `X-Credits-Limit` — повний бюджет кредитів на місяць (за планом)
- `X-Credits-Reset` — ISO-8601 дата оновлення балансу
- `X-RateLimit-*` — поточний стан sliding window (стандартний формат)
- `X-Request-Id` — ULID запиту, використай при зверненні в підтримку

## Скільки вже витрачено — три способи

Перевірити поточний баланс кредитів можна трьома способами — від найшвидшого до найдетальнішого:

1. **У кожній відповіді** — заголовки `X-Credits-Remaining` / `X-Credits-Used` / `X-Credits-Limit` повертаються на **будь-який** запит (навіть на помилку). Нічого додатково викликати не треба — баланс завжди перед очима.
2. **Окремим запитом** — `GET /v1/keys/usage` зі своїм `X-Api-Key` повертає `credits` (used / remaining / limit / reset), `usage` (запитів за today / week / month) і топ-20 ендпоінтів за 30 днів. Один виклик, без окремого admin-ключа.
3. **У дашборді** — [api.astroway.info/dashboard/billing](https://api.astroway.info/dashboard/billing) показує баланс, графік usage і розбивку по ендпоінтах у реальному часі.

```bash frame="terminal"
curl https://api.astroway.info/v1/keys/usage \
  -H "X-Api-Key: $AW_KEY"
```

<Aside type="tip">
На відміну від більшості API (Anthropic, OpenAI), AstroWay повертає **залишок балансу прямо в заголовку кожної відповіді** (`X-Credits-Remaining`) — не треба ходити в дашборд чи окремий usage-API, щоб дізнатися, скільки лишилось.
</Aside>

## Кешування

Ідентичні запити протягом 5 хвилин повертаються з кешу **без списання кредитів**. Це окремий заголовок:

```http
X-Cache: HIT
X-Credits-Used: 0
```

Що вважається «ідентичним»:
- Той самий ендпоінт
- Той самий JSON body (байт-в-байт після нормалізації пробілів)
- Той самий ключ API

Це безпечно, бо всі ендпоінти детерміновані — однаковий input завжди дає однаковий output.

## Стрімінг і вебхуки

### Стрімінг (`/stream/*`)

10 стрім-ендпоінтів тарифікуються як **Tier 1 — 10 кредитів за виклик**. Кожен виклик перераховує позиції планет, тому це повноцінне обчислення, а не кешований lookup — окремої «дешевшої» ставки за тік немає.

Кожна відповідь містить два поля для економного опитування:

- `tickSeconds` — рекомендований інтервал опитування;
- `nextEventAt` — коли стан зміниться наступного разу.

Опитувати частіше за `tickSeconds` — марно палити кредити: стан не зміниться до `nextEventAt`.

<Aside type="caution">
Приклад бюджету: один стрім, опитуваний кожні 60 с = 1 440 викликів/добу × 10 кредитів = 14 400 кредитів/добу. На Indie (50 000/міс) це ~3.5 доби одного стріму. Для постійного стрімінгу — Starter+.
</Aside>

### Вебхуки (`/webhooks/*`)

CRUD-операції керування підпискою (`/webhooks/subscribe`, список, перегляд, видалення, `/test`) коштують **Tier 1 — 10 кредитів** кожна. Це рідкісні виклики.

**Доставка події (сервер → ваш URL) не тарифікується** — кредити списуються лише за CRUD-виклики керування. Підтримується 12 типів подій (`report-ready`, `transit-alert`, `eclipse-alert`, `dasha-change`, `sign-ingress` тощо).

Вебхуки доступні з плану **Pro і вище**.

## Що робити при перевищенні лімітів

### `402 Payment Required` — закінчились кредити

```json
{
  "error": {
    "code": "credits_exhausted",
    "message": "Monthly credit budget exhausted. Upgrade plan or wait for reset.",
    "credits_remaining": 0,
    "credits_reset": "2026-05-01T00:00:00Z",
    "upgrade_url": "https://api.astroway.info/dashboard/billing"
  }
}
```

Варіанти:
- **Апгрейд плану** — одразу отримуєш новий бюджет
- **Overage** (Starter/Pro) — вмикається автоматично, якщо не вимкнено в settings
- **Чекати reset** (Free) — 1 число наступного місяця

### `429 Too Many Requests` — перевищено RPM

```json
{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many requests. Retry after 12 seconds.",
    "retry_after_seconds": 12
  }
}
```

Заголовок `Retry-After: 12` — стандартний HTTP-заголовок, твій HTTP-клієнт має його розуміти.

**Правильна обробка:**

```ts
async function callWithRetry(endpoint: string, body: object) {
  const response = await fetch(endpoint, {
    method: 'POST',
    headers: { 'X-Api-Key': key, 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  });

  if (response.status === 429) {
    const retryAfter = Number(response.headers.get('Retry-After') ?? 1);
    await new Promise((r) => setTimeout(r, retryAfter * 1000));
    return callWithRetry(endpoint, body);
  }

  return response.json();
}
```

<Aside type="caution">
Не роби експоненціальний backoff без cap — `Retry-After` у відповіді вже містить точну цифру. Довіряй їй.
</Aside>

## Оцінка бюджету заздалегідь

Перед інтеграцією прикинь, скільки кредитів тобі потрібно на місяць:

```
monthly_credits = daily_active_users × calls_per_user × avg_cost_per_call × 30
```

Приклад: застосунок на 500 DAU, кожен користувач робить 3 розрахунки карт + 1 синастрію на день:

```
500 × (3 × 20 + 1 × 50) × 30 = 500 × 110 × 30 = 1 650 000 кредитів/міс
→ Business ($199) покриває
```

Калькулятор бюджету — на сторінці [Тарифи](/pricing/).

## Далі

- [Помилки](/errors/) — повний довідник error-кодів
- [Idempotency](/idempotency/) — як робити повторні запити безпечно
