Σφάλματα
Όλα τα σφάλματα επιστρέφονται σε ενιαία μορφή: ok: false μαζί με ένα αντικείμενο error:
{ "ok": false, "error": { "code": "INVALID_API_KEY", "message": "Invalid API key" }}code: κωδικόςUPPER_SNAKE_CASEαναγνώσιμος από μηχανές, σταθερός, δεν αλλάζει χωρίς major αναβάθμιση έκδοσης. Κάνε switch σε αυτόν, όχι στοmessage.message: εξήγηση αναγνώσιμη από άνθρωπο, στα αγγλικά. Το κείμενο μπορεί να βελτιώνεται χωρίς αλλαγή έκδοσης.details: προαιρετικό. Για τοINVALID_INPUTείναι ένας πίνακας{ path, message }για κάθε πεδίο που απέτυχε. Για τοINVALID_FIELDσε κάθε στοιχείο προστίθεται τοexpectedμε το κανονικό όνομα του πεδίου.docs: προαιρετικό, σύνδεσμος σε ενότητα αυτής της σελίδας, όταν για τον κωδικό υπάρχει πιο αναλυτική εξήγηση.request_id: προστίθεται μόνο στις απαντήσεις5xxκαιBAD_JSON. Ανάφερέ το όταν επικοινωνείς με την υποστήριξη.
Κωδικοί HTTP
Ενότητα με τίτλο «Κωδικοί HTTP»| Status | Σημασία |
|---|---|
200 OK | Επιτυχία |
400 Bad Request | Χαλασμένο JSON, πεδία που λείπουν ή αποτυχημένη επικύρωση Zod |
401 Unauthorized | Λείπει ή δεν είναι έγκυρο το X-Api-Key |
402 Payment Required | Απαιτείται ανώτερο πλάνο / πακέτο, ή η συνδρομή είναι ανενεργή |
403 Forbidden | Το κλειδί είναι έγκυρο, αλλά δεν έχει δικαιώματα (scope, origin, suspended) |
404 Not Found | Ο πόρος, το κλειδί ή το job δεν υπάρχει |
422 Unprocessable Entity | Η είσοδος είναι έγκυρη, αλλά η μηχανή δεν μπόρεσε να κάνει τον υπολογισμό |
429 Too Many Requests | Ξεπεράστηκε το rate limit, εξαντλήθηκαν τα credits ή το spend cap |
500 Internal Server Error | Εσωτερικό σφάλμα από τη μεριά μας, ανάφερε το request_id |
503 Service Unavailable | Το AI gateway / η ουρά δεν είναι προσωρινά διαθέσιμα |
Κωδικοί σφάλματος
Ενότητα με τίτλο «Κωδικοί σφάλματος»Αυθεντικοποίηση (401)
Ενότητα με τίτλο «Αυθεντικοποίηση (401)»| Κωδικός | Σημασία |
|---|---|
MISSING_API_KEY | Η κεφαλίδα X-Api-Key δεν στάλθηκε |
INVALID_API_KEY | Το κλειδί δεν υπάρχει ή έχει ανακληθεί |
MISSING_BEARER | Επιλέχθηκε το σχήμα Authorization: Bearer, αλλά λείπει το token |
WRONG_AUTH_METHOD | Στάλθηκε X-Api-Key σε /v1/me/* (μόνο Bearer). Για έλεγχο του κλειδιού: GET /v1/auth/keys/me. Για κλήσεις του API: οποιοδήποτε /v1/* με X-Api-Key |
Δικαιώματα (403)
Ενότητα με τίτλο «Δικαιώματα (403)»| Κωδικός | Σημασία |
|---|---|
INSUFFICIENT_SCOPE | Το κλειδί δεν έχει δικαιώματα για αυτή την ενέργεια |
DOMAIN_MISMATCH / FORBIDDEN_ORIGIN | Το origin του αιτήματος δεν είναι στο allow-list του κλειδιού |
ENDPOINT_NOT_IN_SCOPE | Το κλειδί περιορίζεται σε λίστα endpoints (allowed_endpoints) και αυτή η διαδρομή δεν είναι στη λίστα. Το details αναφέρει τη λίστα |
KEY_SUSPENDED | Το κλειδί έχει ανασταλεί |
Χρέωση (402)
Ενότητα με τίτλο «Χρέωση (402)»| Κωδικός | Σημασία |
|---|---|
PLAN_UPGRADE_REQUIRED | Το endpoint απαιτεί ανώτερο πλάνο ή add-on πακέτο |
PLAN_PACK_MISMATCH | Το endpoint ανήκει σε πακέτο που δεν υπάρχει στο κλειδί |
SUBSCRIPTION_EXPIRED | Η πληρωμένη περίοδος έληξε πριν από περισσότερες από 3 ημέρες. Τις πρώτες 3 ημέρες μετά τη λήξη τα αιτήματα εξυπηρετούνται ακόμη σύμφωνα με το πλάνο και φέρουν την κεφαλίδα X-Subscription-Grace-Ends. Το details περιέχει expired_at, grace_ended_at και renew_url |
Rate limiting και credits (429)
Ενότητα με τίτλο «Rate limiting και credits (429)»| Κωδικός | Σημασία |
|---|---|
RATE_LIMIT | Ξεπεράστηκε το όριο RPM. Η απάντηση περιέχει την κεφαλίδα Retry-After: <sec> |
CREDITS_EXHAUSTED | Ο μηνιαίος προϋπολογισμός credits εξαντλήθηκε |
SPEND_CAP_REACHED | Επιτεύχθηκε το όριο δαπανών για τα AI endpoints |
KEY_BUDGET_EXHAUSTED | Το κλειδί εξάντλησε τον δικό του προϋπολογισμό (credits_cap_cycle). Στον λογαριασμό μπορεί να έχουν μείνει credits: ο περιορισμός αφορά μόνο αυτό το κλειδί |
Επικύρωση (400)
Ενότητα με τίτλο «Επικύρωση (400)»| Κωδικός | Σημασία |
|---|---|
INVALID_INPUT | Ένα ή περισσότερα πεδία απέτυχαν στην επικύρωση Zod. Το details είναι πίνακας { path, message } |
INVALID_FIELD | Το body περιέχει σύντομο όνομα πεδίου αντί για το κανονικό. Βλ. παρακάτω |
MISSING_FIELDS | Λείπει υποχρεωτικό πεδίο |
BAD_JSON | Χαλασμένο JSON στο body του αιτήματος |
Παράδειγμα 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
Ενότητα με τίτλο «INVALID_FIELD»Τα endpoints χαρτών δέχονται μόνο πλήρη ονόματα πεδίων. Οι σύντομες μορφές απορρίπτονται με 400 αντί να διαβάζονται σιωπηλά:
| Στάλθηκε | Κανονικό πεδίο | Τι αναμένεται |
|---|---|---|
lat | latitude | δεκαδικές μοίρες, ο βορράς θετικός |
lng, lon, long | longitude | δεκαδικές μοίρες, η ανατολή θετική |
tz με αριθμό, tzOffset, utcOffset, timezone_offset | timezoneOffset | αριθμός ωρών από το UTC, π.χ. 5.75 |
tz με όνομα, timeZone, time_zone | timezone | όνομα ζώνης IANA, π.χ. Europe/Kyiv, ή auto |
Η απάντηση απαριθμεί όλα τα πεδία που βρέθηκαν με τη μία, με τη σειρά του body του αιτήματος, ώστε η μετονομασία να γίνεται σε ένα πέρασμα:
{ "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 φαίνεται σε ποιον χάρτη αφορά: chart1.lat, όχι απλώς lat.
Ο ίδιος κωδικός επιστρέφεται όταν το timezone δεν μπορεί να αναλυθεί: κενή τιμή, συντομογραφία όπως EST (που είναι σταθερό -5 όλο τον χρόνο, οπότε η Νέα Υόρκη τον Ιούλιο θα βγει λάθος κατά μία ώρα), όνομα που δεν υπάρχει στη βάση ζωνών ώρας, απόκλιση γραμμένη ως κείμενο, όπως +03:00, ή auto χωρίς latitude και longitude. Το μήνυμα υποδεικνύει τι να στείλεις αντί γι’ αυτό, και το path δείχνει το αντικείμενο, για παράδειγμα chart2.timezone.
Δύο πράγματα που αξίζει να λάβεις υπόψη.
Αυτό δεν είναι deprecation. Τα σύντομα ονόματα δεν ήταν ποτέ μέρος του συμβολαίου και δεν εμφανίζονταν στο /openapi.json ως πεδία του body. Μέχρι τις 2026-08-01 δεν λειτουργούσαν, αλλά αγνοούνταν σιωπηλά: οι συντεταγμένες έχουν προεπιλογή το μηδέν, οπότε ο χάρτης υπολογιζόταν για 0°N 0°E σε UTC. Ο ωροσκόπος, οι οίκοι και ό,τι προκύπτει από αυτούς ήταν λάθος, και η απάντηση δεν το ανέφερε. Γι’ αυτό οι σύντομες μορφές δεν γίνονται ξανά δεκτές: δύο ονόματα για ένα πεδίο για πάντα, και το tz επιπλέον είναι αμφίσημο (αριθμός ή όνομα ζώνης).
Το εμφωλευμένο point είναι άλλο πράγμα. Στα /v1/acg-zones, /v1/acg/by-category, /v1/ccg-analysis και /v1/eclipse-analysis το αντικείμενο point: { lat, lng } έχει δηλωμένα ονόματα πεδίων, και αυτά περνούν.
Συντεταγμένες που λείπουν: 400 από τις 2026-11-09
Ενότητα με τίτλο «Συντεταγμένες που λείπουν: 400 από τις 2026-11-09»Το σωστό όνομα πεδίου είναι το μισό ζητούμενο. Ένα body χωρίς latitude και longitude έδινε επίσης 200, γιατί οι συντεταγμένες είχαν προεπιλογή το μηδέν, και η απάντηση περιέγραφε το 0°N 0°E.
Μέχρι τις 2026-11-09 ένα τέτοιο αίτημα λειτουργεί, αλλά η απάντηση φέρει Deprecation: true, Sunset, Warning και το πεδίο _warning στο body. Από τις 2026-11-09 είναι 400 INVALID_INPUT με latitude is required, in decimal degrees.
Τα ρητά latitude: 0, longitude: 0 παραμένουν έγκυρα: το ζήτημα είναι το πεδίο που λείπει, όχι η τιμή. Το timezoneOffset κρατά την προεπιλογή μηδέν, γιατί εκεί το μηδέν σημαίνει UTC. Το city δεν αντικαθιστά τις συντεταγμένες: κανείς δεν το γεωκωδικοποιεί. Ο έλεγχος εφαρμόζεται μόνο σε αντικείμενα που φέρουν ταυτόχρονα date και time.
Σφάλματα υπολογισμού (422)
Ενότητα με τίτλο «Σφάλματα υπολογισμού (422)»| Κωδικός | Σημασία |
|---|---|
CALCULATION_ERROR | Η είσοδος είναι έγκυρη, αλλά η μηχανή δεν μπόρεσε να κάνει τον υπολογισμό (για παράδειγμα, πολικό γεωγραφικό πλάτος για Placidus). Δοκίμασε Whole Sign / Equal ή άλλη ημερομηνία. |
Σφάλματα server
Ενότητα με τίτλο «Σφάλματα server»| Κωδικός | HTTP | Σημασία |
|---|---|---|
INTERNAL_ERROR | 500 | Απρόσμενο σφάλμα. Το καταγράφουμε με stack trace, ανάφερε το request_id |
GATEWAY_UNAVAILABLE / AI_UNAVAILABLE / LLM_UNAVAILABLE | 503 | Το AI gateway δεν είναι διαθέσιμο. Retry με εκθετικό backoff |
QUEUE_UNAVAILABLE | 503 | Η ουρά εργασιών παρασκηνίου δεν είναι διαθέσιμη |
Χειρισμός στον κώδικα του client
Ενότητα με τίτλο «Χειρισμός στον κώδικα του client»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})` : ''}`); }}Κάνε switch στο code, όχι στο message. Τα επίσημα SDK (@astroway/sdk, astroway) πετούν τυποποιημένες υποκλάσεις σφαλμάτων ανάλογα με το HTTP status (AuthenticationError, RateLimitError, BadRequestError …), οπότε δεν θα χρειαστεί να γράψεις κώδικα χειρισμού.
Αίτημα υποστήριξης
Ενότητα με τίτλο «Αίτημα υποστήριξης»Για να επικοινωνήσεις, στείλε στο support@astroway.info:
- Το
request_idαπό την απάντηση (αν είναι5xx) - Το endpoint και ένα συντομευμένο JSON body (χωρίς μυστικά)
- Αναμενόμενη συμπεριφορά σε σχέση με την πραγματική
- Ζώνη ώρας και κατά προσέγγιση ώρα του αιτήματος (UTC)
Η απάντηση δίνεται εντός του SLA του πλάνου σου (48 ώρες Starter, 24 ώρες Pro, ατομικό για Enterprise).