# Автентифікація

Майже всі запити до AstroWay API автентифікуються через header `X-Api-Key`. Винятки: 14 ендпоінтів `/v1/reference/*` (signs, planets, houses, aspects, …) працюють публічно без ключа з обмеженням 30 запитів / годину на IP.

<GetApiKeyBlock variant="compact" /> Для всіх **обчислювальних ендпоінтів `/v1/*`** (chart, synastry, transits, /reports, /tarot тощо) — лише `X-Api-Key`. Для **користувацьких операцій `/v1/me/*`** (`GET /me`, `DELETE /me/account`) — Bearer JWT, виданий через `/v1/auth/login`. OAuth/session-cookies на публічному API не використовуються. **Reference-словники `/v1/reference/*`** — без ключа, безкоштовно (канонічні lookup-таблиці).

## Формат ключа

```
aw_live_aB3xY7pQ9rN2mK4jH8vC5tL6wZ1fD0eR
aw_test_aB3xY7pQ9rN2mK4jH8vC5tL6wZ1fD0eR
```

- `aw_live_` — production, списує кредити з балансу
- `aw_test_` — sandbox, запити повертають стабовий відгук (або мінімальний реальний розрахунок), **не списують кредити**, відмічені в dashboard окремо
- Після префікса — 32 символи base62, криптографічно випадкові
- Ключ показується в чистому вигляді **лише один раз** при створенні. Далі в dashboard — тільки перші й останні 4 символи.

## Заголовок запиту

```http
POST /v1/chart HTTP/1.1
Host: api.astroway.info
X-Api-Key: aw_live_aB3xY7pQ9rN2mK4jH8vC5tL6wZ1fD0eR
Content-Type: application/json
```

## Postman collection

Якщо для тебе зручніше Postman, ніж curl/SDK — є готова collection з усіма {siteMeta.endpoints} endpoints, перерозбита по 55 теках за OpenAPI tags, з підставленими прикладами запитів. Auth налаштований на collection-рівні: вставляєш ключ в `apiKey` variable один раз, всі запити підхоплюють.

- **Published docs:** [documenter.getpostman.com/view/54689779/2sBXqNmy3n](https://documenter.getpostman.com/view/54689779/2sBXqNmy3n)
- **Public workspace:** [postman.com/astroway-info/astroway-api](https://www.postman.com/astroway-info/astroway-api)
- **Скачати JSON:** [astroway-api.json](/postman/astroway-api.json) (≈ 5 MB) — імпортуй напряму в Postman або Insomnia

Collection auto-generated з [OpenAPI spec](https://api.astroway.info/v1/openapi.json) — оновлюється з кожним деплоєм.

## Створення і керування ключами

Через dashboard:
- [api.astroway.info/dashboard/keys](https://api.astroway.info/dashboard/keys)
- Можна мати до **10 активних ключів** на акаунт одночасно
- Кожен ключ має label (наприклад `production-backend`, `ci-tests`, `local-dev`)

Через API (для self-service інтеграцій):

<Tabs syncKey="lang">
  <TabItem label="cURL">
    ```bash frame="terminal"
    curl -X POST https://api.astroway.info/v1/keys \
      -H "X-Api-Key: aw_live_master_key" \
      -H "Content-Type: application/json" \
      -d '{"label": "ci-tests", "mode": "test"}'
    ```
  </TabItem>
  <TabItem label="TypeScript">
    ```ts
    // Equivalent через @astroway/sdk: aw.client.POST('/keys', { body: { label, mode } })
    const r = await fetch('https://api.astroway.info/v1/keys', {
      method: 'POST',
      headers: {
        'X-Api-Key': process.env.ASTROWAY_MASTER_KEY!,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ label: 'ci-tests', mode: 'test' }),
    });

    const { data: created } = await r.json();
    console.log(created.key); // shown once — store it now
    ```
  </TabItem>
  <TabItem label="Python">
    ```python
    # Equivalent через `astroway` (PyPI): aw.post('/keys', body={'label': ..., 'mode': ...})

    r = requests.post(
        'https://api.astroway.info/v1/keys',
        headers={'X-Api-Key': os.environ['ASTROWAY_MASTER_KEY']},
        json={'label': 'ci-tests', 'mode': 'test'},
    )
    created = r.json()['data']
    print(created['key'])  # shown once — store it now
    ```
  </TabItem>
  <TabItem label="PHP">
    ```php
    <?php
    use GuzzleHttp\Client;

    $aw = new Client(['base_uri' => 'https://api.astroway.info/v1/']);
    $r = $aw->post('keys', [
        'headers' => ['X-Api-Key' => getenv('ASTROWAY_MASTER_KEY')],
        'json' => ['label' => 'ci-tests', 'mode' => 'test'],
    ]);

    $created = json_decode($r->getBody(), true);
    echo $created['key']; // shown once — store it now
    ```
  </TabItem>
</Tabs>

<Aside type="tip">
Master-ключ (той, що ти створив у dashboard) може керувати іншими ключами через `/v1/keys`. Регулярні ключі — не можуть. Це прописано в `scope` ключа.
</Aside>

## Best practices

### 1. Ніколи не клади ключ у фронтенд

Ключ — секрет backend-рівня. Якщо він потрапляє в JS, що виконується в браузері користувача — його видно в DevTools і він витече.

**Правильно:** свій backend тримає ключ, фронтенд б'ється в твій backend, твій backend — в AstroWay API.

**Неправильно:**

```ts
// ❌ НЕ РОБИ ТАК
fetch('https://api.astroway.info/v1/chart', {
  headers: { 'X-Api-Key': 'aw_live_...' }, // видно в браузері
});
```

### 2. Environment variables, не hardcode

```bash
# .env (в .gitignore)
ASTROWAY_API_KEY=aw_live_...
```

```ts
// у коді
const key = process.env.ASTROWAY_API_KEY;
if (!key) throw new Error('ASTROWAY_API_KEY is not set');
```

### 3. Окремі ключі на різні середовища

- `production-backend` — продакшен
- `staging-backend` — staging
- `ci-tests` — CI/CD pipeline
- `local-dev-maksym` — локальна розробка кожного розробника

Якщо один ключ скомпрометовано — revoke саме його, інші продовжують працювати.

### 4. Ротація

Рекомендована частота — **раз на 90 днів**. Або негайно, якщо є підозра на витік.

Ротація без downtime:
1. Створи новий ключ з тим самим label + `-v2`
2. Розгорни його в прод (паралельно зі старим)
3. Переконайся, що usage тече на новий ключ (dashboard)
4. Revoke старий

### 5. Моніторинг usage

Dashboard показує запити по ключах окремо. Якщо раптом один ключ почав робити в 10× більше запитів, ніж зазвичай — це сигнал перевірити.

Можна поставити alert: `Settings → Notifications → Alert when daily credits > X`.

## Помилки автентифікації

| Код | Значення |
|---|---|
| `401 Unauthorized` | Header `X-Api-Key` відсутній або ключ невалідний |
| `403 Forbidden` | Ключ валідний, але не має scope для цієї дії (наприклад, звичайний ключ намагається керувати іншими ключами) |
| `402 Payment Required` | Кредити закінчились (на Free) або передплата неактивна |
| `429 Too Many Requests` | Перевищено rate limit (10/60/300 req/min залежно від плану) |

Приклад `401`:

```json
{
  "error": {
    "code": "invalid_api_key",
    "message": "The API key provided is invalid or has been revoked.",
    "request_id": "01HXY2A7ZM..."
  }
}
```

## Sandbox mode

Ключі з префіксом `aw_test_` працюють у sandbox:

- Не списують кредити
- Повертають стабовий або мінімальний реальний відгук
- Не впливають на статистику production
- Доступні ендпоінти — ті ж самі

Корисно для CI/CD, e2e тестів і локальної розробки. Створюється через dashboard одним кліком.

## Далі

- [Кредити та ліміти](/rate-limits-credits/) — як працює білінг і rate limiting
- [Помилки](/errors/) — повний перелік error-кодів
