Автентифікація
Майже всі запити до AstroWay API автентифікуються через header X-Api-Key. Винятки: 14 ендпоінтів /v1/reference/* (signs, planets, houses, aspects, …) працюють публічно без ключа з обмеженням 30 запитів / годину на IP. Якщо запити робить ваш сервер, надішліть заголовок X-AstroWay-Site-URL і ліміт стане 300 запитів / годину на сайт: деталі.
Для всіх обчислювальних ендпоінтів /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-таблиці).
Формат ключа
Section titled “Формат ключа”aw_live_aB3xY7pQ9rN2mK4jH8vC5tL6wZ1fD0eRaw_test_aB3xY7pQ9rN2mK4jH8vC5tL6wZ1fD0eRaw_live_: production, списує кредити з балансуaw_test_: sandbox, запити повертають стабовий відгук (або мінімальний реальний розрахунок), не списують кредити, відмічені в dashboard окремо- Після префікса: 32 символи base62, криптографічно випадкові
- Ключ показується в чистому вигляді лише один раз при створенні. Далі в dashboard - тільки перші й останні 4 символи.
Заголовок запиту
Section titled “Заголовок запиту”POST /v1/chart HTTP/1.1Host: api.astroway.infoX-Api-Key: aw_live_aB3xY7pQ9rN2mK4jH8vC5tL6wZ1fD0eRContent-Type: application/jsonPostman collection
Section titled “Postman collection”Якщо для тебе зручніше Postman, ніж curl/SDK - є готова collection з усіма 771 endpoints, перерозбита по 55 теках за OpenAPI tags, з підставленими прикладами запитів. Auth налаштований на collection-рівні: вставляєш ключ в apiKey variable один раз, всі запити підхоплюють.
- Published docs: documenter.getpostman.com/view/54689779/2sBXqNmy3n
- Public workspace: postman.com/astroway-info/astroway-api
- Скачати JSON: astroway-api.json (≈ 5 MB) - імпортуй напряму в Postman або Insomnia
Collection auto-generated з OpenAPI spec - оновлюється з кожним деплоєм.
Створення і керування ключами
Section titled “Створення і керування ключами”Через dashboard:
- api.astroway.info/dashboard/keys
- Можна мати до 10 активних ключів на акаунт одночасно
- Кожен ключ має ім’я, поле
name(наприкладproduction-backend,ci-tests,local-dev)
Через API (для self-service інтеграцій):
curl -X POST https://api.astroway.info/v1/keys \ -H "X-Api-Key: aw_live_master_key" \ -H "Content-Type: application/json" \ -d '{"name": "ci-tests", "mode": "test"}'// Equivalent via @astroway/sdk: aw.client.POST('/keys', { body: { name, 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({ name: 'ci-tests', mode: 'test' }),});
const { data: created } = await r.json();console.log(created.api_key); // shown once - store it now# Equivalent via `astroway` (PyPI): aw.post('/keys', body={'name': ..., 'mode': ...})import os, requests
r = requests.post( 'https://api.astroway.info/v1/keys', headers={'X-Api-Key': os.environ['ASTROWAY_MASTER_KEY']}, json={'name': 'ci-tests', 'mode': 'test'},)created = r.json()['data']print(created['api_key']) # shown once - store it now<?phpuse 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' => ['name' => 'ci-tests', 'mode' => 'test'],]);
$created = json_decode($r->getBody(), true)['data'];echo $created['api_key']; // shown once - store it nowКлючі для браузера
Section titled “Ключі для браузера”Типовий ключ server-only: якщо запит із ним несе заголовок Origin або
Referer, приходить 403 ORIGIN_FORBIDDEN. Це навмисно, і це те, що ловить
ключ, випадково залишений у фронтенді.
Коли віджет або сторінка мають ходити в API з браузера, ключ створюється
одразу з політикою походження. Поле origin_restriction у POST /v1/keys:
type | Що дозволено | Коли брати |
|---|---|---|
server-only (типово) | тільки запити без Origin і Referer | бекенд, cron, CI |
public | тільки перелічені хости, і запит зобов’язаний нести походження | віджет чи сторінка на вашому домені, ключ у вихідному коді |
allowlist | те саме, що public | застаріле написання: приймається й далі, але в openapi.json більше не значиться |
curl -X POST https://api.astroway.info/v1/keys \ -H "X-Api-Key: aw_live_master_key" \ -H "Content-Type: application/json" \ -d '{ "name": "site-widget", "origin_restriction": { "type": "public", "allowed_origins": ["example.com", "*.example.com"] }, "credits_cap_cycle": 20000, "allowed_endpoints": ["chart", "public/*"] }'Правила зіставлення, перевірені на проді:
- До 20 хостів на ключ. Схема (
https://) і порт ігноруються, регістр не має значення. www.знімається з вхідного хоста, тожexample.comпокриває іwww.example.com. Окремо додавати форму зwww.не треба, вона нічого не змінює.*.example.comпокриває піддомени (app.example.com), але не самexample.com. Апекс перелічується окремим рядком, як у прикладі вище.- Хост не зі списку отримує
403 ORIGIN_NOT_ALLOWEDіз самим хостом у поліincoming_origin, щоб було видно, який рядок бракує. Refererрахується нарівні зOrigin: браузер надсилає його там, деOriginнемає.
Змінити список у вже створеного ключа
Section titled “Змінити список у вже створеного ключа”PATCH /v1/keys/{id} переписує список, не чіпаючи сам ключ. Право доступу те саме, що й у POST /v1/keys вище; у дашборді це пункт “Змінити походження” в меню ключа.
curl -X PATCH https://api.astroway.info/v1/keys/433 \ -H "X-Api-Key: aw_live_master_key" \ -H "Content-Type: application/json" \ -d '{ "origin_restriction": { "type": "public", "allowed_origins": ["example.com", "*.example.com"] } }'Новий список діє з наступного ж запиту: кеш ключа скидається під час запису, чекати хвилину не треба. Сам рядок ключа не змінюється, тож ані сторінку, ані бекенд перевипускати не потрібно. Після POST /v1/keys/{id}/rotate список зберігається, а старе значення ключа перестає працювати одразу.
Клас ключа не редагується, бо він записаний у самому ключі:
| Спроба | Відповідь |
|---|---|
pk_ зробити server-only | 400: клас є частиною ключа, треба відкликати і створити новий |
aw_ дати список доменів | 400: браузерний ключ це інший клас, він створюється як public |
pk_ з порожнім списком | 400: ключ без списку відхиляв би кожен запит |
pk_ без бюджету чи області (null) | 400: ключ для браузера завжди обмежений обома, їх можна змінити, але не зняти |
Бюджет кредитів на окремий ключ
Section titled “Бюджет кредитів на окремий ключ”Кредити спільні на весь акаунт, тож один ключ може витратити їх усі. Для бекенд-ключа це нормально, для ключа у вихідному коді сторінки ні: список доменів каже, звідки можна звертатись, але не каже, скільки це може коштувати.
credits_cap_cycle у тому ж PATCH /v1/keys/{id} обмежує саме цей ключ:
curl -X PATCH https://api.astroway.info/v1/keys/433 \ -H "X-Api-Key: aw_live_master_key" \ -H "Content-Type: application/json" \ -d '{"credits_cap_cycle": 5000}'null знімає обмеження (крім ключа pk_, у нього бюджет можна змінити, але не зняти). 0 означає ключ, яким не можна витратити нічого: спосіб припаркувати ключ, не відкликаючи його. Лічильник той самий, що й у кредитів, і обнуляється разом із циклом тарифу.
Коли ключ упирається у свій бюджет, приходить 429 KEY_BUDGET_EXHAUSTED, навіть якщо на акаунті кредити ще лишились, і навіть на тарифі з overage: бюджет, який можна перевитратити за гроші, це не бюджет. Поки бюджет заданий, кожна відповідь несе X-Key-Budget-Limit і X-Key-Budget-Remaining.
Область ендпоінтів
Section titled “Область ендпоінтів”Ключ без області викликає все, що входить у тариф. allowed_endpoints звужує його до списку шляхів: точного (chart) або простору імен (embed/*). Це третє, незалежне обмеження: список доменів каже звідки, бюджет скільки, область що саме.
curl -X PATCH https://api.astroway.info/v1/keys/433 \ -H "X-Api-Key: aw_live_master_key" \ -H "Content-Type: application/json" \ -d '{"allowed_endpoints": ["embed/*", "public/moon-phase"]}'null знімає обмеження (крім ключа pk_, у нього область обов’язкова). Порожній список не приймається: він однаково читався б і як “усе”, і як “нічого”. Шляхи пишуться відносно /v1, без початкового слеша, регістр значення не має.
Виклик поза списком отримує 403 ENDPOINT_NOT_IN_SCOPE, а details називає сам список, щоб не доводилось вгадувати. Область діє на обидва класи ключів і на /v1/public/* та /v1/embed/* так само, як на решту. Службові читання з-під неї не звільнені, на відміну від кредитів: ключ, звужений до embed/*, не прочитає й власну статистику. Це навмисно, бо ключ у вихідному коді сторінки не повинен віддавати відвідувачу витрати акаунта, а керувати ключем це не заважає: дашборд ходить сесією, а не ключем.
Best practices
Section titled “Best practices”1. Не клади server-only ключ у фронтенд
Section titled “1. Не клади server-only ключ у фронтенд”Типовий ключ - секрет backend-рівня. Якщо він потрапляє в JS, що виконується в браузері користувача - його видно в DevTools і він витече. Саме тому такий ключ відповідає 403 ORIGIN_FORBIDDEN на будь-який запит із Origin чи Referer.
Якщо звертатися з браузера все ж треба, це робиться не звичайним ключем, а окремим, створеним із origin_restriction.type: "public": ключі для браузера. Такий ключ має префікс pk_, його теж видно в DevTools, і в цьому вся суть - його цінність обмежена списком ваших доменів, а запит без походження він відхиляє.
Правильно: свій backend тримає ключ, фронтенд б’ється в твій backend, твій backend - в AstroWay API.
Неправильно:
// DO NOT DO THISfetch('https://api.astroway.info/v1/chart', { headers: { 'X-Api-Key': 'aw_live_...' }, // visible in browser});2. Environment variables, не hardcode
Section titled “2. Environment variables, не hardcode”# .env (in .gitignore)ASTROWAY_API_KEY=aw_live_...// in codeconst key = process.env.ASTROWAY_API_KEY;if (!key) throw new Error('ASTROWAY_API_KEY is not set');3. Окремі ключі на різні середовища
Section titled “3. Окремі ключі на різні середовища”production-backend: продакшенstaging-backend: stagingci-tests: CI/CD pipelinelocal-dev-maksym: локальна розробка кожного розробника
Якщо один ключ скомпрометовано - revoke саме його, інші продовжують працювати.
4. Ротація
Section titled “4. Ротація”Рекомендована частота - раз на 90 днів. Або негайно, якщо є підозра на витік.
Ротація без downtime:
- Створи новий ключ з тим самим
name+-v2 - Розгорни його в прод (паралельно зі старим)
- Переконайся, що usage тече на новий ключ (dashboard)
- Revoke старий
5. Моніторинг usage
Section titled “5. Моніторинг usage”Dashboard показує запити по ключах окремо. Якщо раптом один ключ почав робити в 10× більше запитів, ніж зазвичай - це сигнал перевірити.
Можна поставити alert: Settings → Notifications → Alert when daily credits > X.
Помилки автентифікації
Section titled “Помилки автентифікації”| Код | Значення |
|---|---|
401 Unauthorized | Header X-Api-Key відсутній або ключ невалідний |
403 Forbidden | Ключ валідний, але не має scope для цієї дії (наприклад, звичайний ключ намагається керувати іншими ключами) |
403 PUBLISHABLE_KEY_UNBOUNDED | Ключ pk_ без бюджету credits_cap_cycle чи без області allowed_endpoints: задайте обидва в налаштуваннях ключа |
402 Payment Required | Кредити закінчились (на Free) або передплата неактивна |
429 Too Many Requests | Перевищено rate limit (10/60/300 req/min залежно від плану) |
Приклад 401:
{ "error": { "code": "invalid_api_key", "message": "The API key provided is invalid or has been revoked.", "request_id": "8aec43e9bc749b37e998a489bbad1757" }}Sandbox mode
Section titled “Sandbox mode”Ключі з префіксом aw_test_ працюють у sandbox:
- Не списують кредити
- Повертають стабовий або мінімальний реальний відгук
- Не впливають на статистику production
- Доступні ендпоінти: ті ж самі
Корисно для CI/CD, e2e тестів і локальної розробки. Створюється через dashboard одним кліком.
- Кредити та ліміти: як працює білінг і rate limiting
- Помилки: повний перелік error-кодів