エラー
すべてのエラーは統一された形式、つまり ok: false と error オブジェクトで返されます。
{ "ok": false, "error": { "code": "INVALID_API_KEY", "message": "Invalid API key" }}code: 機械可読なUPPER_SNAKE_CASEのコードで、安定 しており、メジャーバージョンを上げない限り変わりません。分岐はmessageではなくこれで行ってください。message: 人が読むための英語の説明です。文言はバージョンを上げずに調整されることがあります。details: 任意です。INVALID_INPUTでは、失敗した各フィールドについての{ path, message }の配列です。INVALID_FIELDでは、各要素に正規のフィールド名を示すexpectedが加わります。docs: 任意です。そのコードに詳しい説明がある場合、このページの該当セクションへのリンクです。request_id:5xxとBAD_JSONのレスポンスにのみ付きます。サポートに問い合わせる際に伝えてください。
HTTP コード
Section titled “HTTP コード”| ステータス | 意味 |
|---|---|
200 OK | 成功 |
400 Bad Request | 壊れた JSON、フィールドの欠落、または Zod の検証失敗 |
401 Unauthorized | X-Api-Key がない、または無効 |
402 Payment Required | 上位のプランやパックが必要、またはサブスクリプションが無効 |
403 Forbidden | キーは有効だが権限がない (scope、origin、suspended) |
404 Not Found | リソース、キー、またはジョブが存在しない |
422 Unprocessable Entity | 入力は有効だが、エンジンが計算できなかった |
429 Too Many Requests | レート制限の超過、クレジットの枯渇、または spend-cap への到達 |
500 Internal Server Error | 内部エラー、こちら側の問題です。request_id を伝えてください |
503 Service Unavailable | AI ゲートウェイまたはキューが一時的に利用できない |
エラーコード
Section titled “エラーコード”認証 (401)
Section titled “認証 (401)”| コード | 意味 |
|---|---|
MISSING_API_KEY | X-Api-Key ヘッダーが送られていない |
INVALID_API_KEY | キーが存在しない、または revoke 済み |
MISSING_BEARER | Authorization: Bearer スキームが選ばれているが、トークンがない |
WRONG_AUTH_METHOD | /v1/me/* (Bearer のみ) に X-Api-Key が送られた。キーの確認には GET /v1/auth/keys/me、API の呼び出しには X-Api-Key 付きの任意の /v1/* を使います |
権限 (403)
Section titled “権限 (403)”| コード | 意味 |
|---|---|
INSUFFICIENT_SCOPE | キーにこの操作の権限がない |
DOMAIN_MISMATCH / FORBIDDEN_ORIGIN | リクエストのオリジンがキーの allow-list にない |
ENDPOINT_NOT_IN_SCOPE | キーがエンドポイントの一覧 (allowed_endpoints) で制限されており、このパスは一覧にない。details に一覧が入ります |
KEY_SUSPENDED | キーが停止されている |
課金 (402)
Section titled “課金 (402)”| コード | 意味 |
|---|---|
PLAN_UPGRADE_REQUIRED | エンドポイントに上位のプランまたはアドオンパックが必要 |
PLAN_PACK_MISMATCH | エンドポイントがキーにないパックに含まれている |
SUBSCRIPTION_EXPIRED | 支払い済みの期間が 3 日以上前に終了した。終了後の最初の 3 日間は、リクエストは引き続きプランどおりに処理され、X-Subscription-Grace-Ends ヘッダーが付きます。details には expired_at、grace_ended_at、renew_url が含まれます |
レート制限とクレジット (429)
Section titled “レート制限とクレジット (429)”| コード | 意味 |
|---|---|
RATE_LIMIT | RPM の制限を超過した。レスポンスには Retry-After: <sec> ヘッダーが含まれます |
CREDITS_EXHAUSTED | 月間のクレジット予算を使い切った |
SPEND_CAP_REACHED | AI エンドポイントの支出上限に達した |
KEY_BUDGET_EXHAUSTED | キーが自身の予算 (credits_cap_cycle) を使い切った。アカウントにはクレジットが残っている場合があります。制限はこのキーだけに適用されます |
検証 (400)
Section titled “検証 (400)”| コード | 意味 |
|---|---|
INVALID_INPUT | 1 つ以上のフィールドが Zod の検証に失敗した。details は { path, message } の配列です |
INVALID_FIELD | ボディに正規の名前ではなく短縮形のフィールド名が含まれている。下記を参照してください |
MISSING_FIELDS | 必須フィールドがない |
BAD_JSON | リクエストボディの JSON が壊れている |
400 の例:
{ "ok": false, "error": { "code": "INVALID_INPUT", "message": "Validation failed: date: Invalid input: expected string, received undefined", "details": [ { "path": "date", "message": "Invalid input: expected string, received undefined" }, { "path": "time", "message": "Invalid input: expected string, received undefined" } ] }}INVALID_FIELD
Section titled “INVALID_FIELD”チャート系のエンドポイントは、完全なフィールド名だけを受け付けます。短縮形は黙って読まれるのではなく、400 で拒否されます。
| 送られたもの | 正規のフィールド | 期待される値 |
|---|---|---|
lat | latitude | 10 進数の度、北が正 |
lng, lon, long | longitude | 10 進数の度、東が正 |
数値の tz、tzOffset、utcOffset、timezone_offset | timezoneOffset | UTC からの時間数、例: 5.75 |
名前の tz、timeZone、time_zone | timezone | IANA のゾーン名、例: Europe/Kyiv、または auto |
レスポンスは見つかったフィールドを すべて 一度に、リクエストボディの順で列挙するため、名前の変更は一回の作業で済みます。
{ "ok": false, "error": { "code": "INVALID_FIELD", "message": "Unsupported fields: \"tz\", \"lat\", \"lng\". Rename them to \"timezoneOffset\", \"latitude\", \"longitude\". See details for what each one expects.", "details": [ { "path": "tz", "expected": "timezoneOffset", "message": "numeric hours from UTC, e.g. 5.75; a zone name goes in timezone" }, { "path": "lat", "expected": "latitude", "message": "decimal degrees, north positive" }, { "path": "lng", "expected": "longitude", "message": "decimal degrees, east positive" } ], "docs": "https://api.astroway.info/en/errors/#invalid_field" }}path は完全なパスを示すため、synastry ではどちらのチャートかがわかります。単なる lat ではなく chart1.lat です。
timezone を解釈できない場合にも同じコードが返ります。空の値、EST のような略称 (これは 1 年中 -5 固定なので、7 月のニューヨークは 1 時間ずれます)、タイムゾーンのデータベースにない名前、+03:00 のように文字列で書かれたオフセット、latitude と longitude のない auto などです。メッセージは代わりに何を送るべきかを示し、path は chart2.timezone のようにオブジェクトを指します。
注意すべき点が 2 つあります。
これは非推奨化ではありません。 短縮形の名前が契約に含まれたことは一度もなく、/openapi.json にもボディのフィールドとして載っていませんでした。2026-08-01 までは機能しておらず、黙って無視されていました。座標のデフォルトが 0 なので、チャートは UTC の 0°N 0°E で計算されていたのです。アセンダント、ハウス、そこから導かれるものはすべて誤っており、レスポンスはそれを知らせませんでした。そのため短縮形を再び受け付けることはしません。1 つのフィールドに 2 つの名前を永久に持つことになり、しかも tz は曖昧です (数値なのかゾーン名なのか)。
入れ子の point は別物です。 /v1/acg-zones、/v1/acg/by-category、/v1/ccg-analysis、/v1/eclipse-analysis のオブジェクト point: { lat, lng } は宣言済みのフィールド名であり、そのまま通ります。
座標がない場合: 2026-11-09 から 400
Section titled “座標がない場合: 2026-11-09 から 400”正しいフィールド名は半分にすぎません。latitude と longitude の ない ボディも 200 を返していました。座標のデフォルトが 0 だったため、レスポンスは 0°N 0°E を記述していたのです。
2026-11-09 まではこのようなリクエストも動作しますが、レスポンスには Deprecation: true、Sunset、Warning ヘッダーと、ボディの _warning フィールドが付きます。2026-11-09 からは latitude is required, in decimal degrees を伴う 400 INVALID_INPUT になります。
明示的な latitude: 0, longitude: 0 は引き続き有効です。問題はフィールドがないことであり、値ではありません。timezoneOffset はデフォルトの 0 を保持します。そこでは 0 が UTC を意味するからです。city は座標の代わりにはなりません。誰もジオコーディングしないからです。このチェックは、date と time を両方持つオブジェクトにだけ適用されます。
計算エラー (422)
Section titled “計算エラー (422)”| コード | 意味 |
|---|---|
CALCULATION_ERROR | 入力は有効だが、エンジンが計算できなかった (例: Placidus での極地の緯度)。Whole Sign / Equal か、別の日付を試してください。 |
| コード | HTTP | 意味 |
|---|---|---|
INTERNAL_ERROR | 500 | 予期しないエラー。スタックトレース付きで記録しています。request_id を伝えてください |
GATEWAY_UNAVAILABLE / AI_UNAVAILABLE / LLM_UNAVAILABLE | 503 | AI ゲートウェイが利用できない。指数バックオフでリトライしてください |
QUEUE_UNAVAILABLE | 503 | バックグラウンドジョブのキューが利用できない |
クライアントコードでの処理
Section titled “クライアントコードでの処理”type ApiError = { ok: false; error: { code: string; message: string; details?: unknown; request_id?: string; };};
async function chart(input: ChartInput) { const res = await fetch('https://api.astroway.info/v1/chart', { method: 'POST', headers: { 'X-Api-Key': process.env.ASTROWAY_API_KEY!, 'Content-Type': 'application/json', }, body: JSON.stringify(input), });
const body = await res.json(); if (!body.ok) { throw new AstrowayError(body.error.code, body.error.message, body.error.request_id); }
return body.data;}
class AstrowayError extends Error { constructor( public code: string, message: string, public requestId?: string, ) { super(`[${code}] ${message}${requestId ? ` (request_id=${requestId})` : ''}`); }}分岐は message ではなく code で行ってください。公式 SDK (@astroway/sdk、astroway) は HTTP ステータスに応じて型付きのエラーサブクラス (AuthenticationError、RateLimitError、BadRequestError …) を投げるため、処理コードを書く必要はありません。
サポートへの問い合わせ
Section titled “サポートへの問い合わせ”問い合わせの際は support@astroway.info に次の情報を送ってください。
- レスポンスの
request_id(5xxの場合) - エンドポイントと、短くした JSON ボディ (秘密情報は除く)
- 期待した動作と実際の動作
- タイムゾーンとおおよそのリクエスト時刻 (UTC)
回答はプランの SLA の範囲内で行います (Starter は 48 時間、Pro は 24 時間、Enterprise は個別)。