Salta ai contenuti
AstroWay/api v2.254.12 · it
tutti i sistemi sono operativi

Errori

Tutti gli errori vengono restituiti in un formato unico: ok: false più un oggetto error:

{
"ok": false,
"error": {
"code": "INVALID_API_KEY",
"message": "Invalid API key"
}
}
  • code: codice UPPER_SNAKE_CASE leggibile dalle macchine, stabile, non cambia senza un bump della versione major. Fai lo switch su di esso, non su message.
  • message: spiegazione leggibile dalle persone, in inglese. Il testo può essere precisato senza bump.
  • details: facoltativo. Per INVALID_INPUT è un array di { path, message } per ogni campo non valido. Per INVALID_FIELD a ogni elemento si aggiunge expected con il nome canonico del campo.
  • docs: facoltativo, link alla sezione di questa pagina quando per il codice c’è una spiegazione più dettagliata.
  • request_id: aggiunto solo alle risposte 5xx e BAD_JSON; citalo quando contatti il supporto.
StatoSignificato
200 OKSuccesso
400 Bad RequestJSON malformato, campi mancanti o validazione Zod fallita
401 UnauthorizedX-Api-Key mancante o non valida
402 Payment RequiredServe un piano o un pack superiore, oppure l’abbonamento non è attivo
403 ForbiddenLa chiave è valida ma mancano i permessi (scope, origin, sospensione)
404 Not FoundLa risorsa, la chiave o il job non esiste
422 Unprocessable EntityL’input è valido, ma il motore non è riuscito a calcolare
429 Too Many RequestsRate limit superato, crediti o spend cap esauriti
500 Internal Server ErrorErrore interno, dalla nostra parte: cita il request_id
503 Service UnavailableGateway AI / coda temporaneamente non disponibili
CodiceSignificato
MISSING_API_KEYL’header X-Api-Key non è stato inviato
INVALID_API_KEYLa chiave non esiste o è stata revocata
MISSING_BEARERÈ stato scelto lo schema Authorization: Bearer, ma il token manca
WRONG_AUTH_METHODSu /v1/me/* (solo Bearer) è stata inviata X-Api-Key. Per verificare la chiave usa GET /v1/auth/keys/me; per le chiamate API qualsiasi /v1/* con X-Api-Key
CodiceSignificato
INSUFFICIENT_SCOPELa chiave non ha i permessi per questa azione
DOMAIN_MISMATCH / FORBIDDEN_ORIGINL’origin della richiesta non è nell’allow-list della chiave
ENDPOINT_NOT_IN_SCOPELa chiave è limitata a un elenco di endpoint (allowed_endpoints), e questo percorso non è nell’elenco. details riporta l’elenco
KEY_SUSPENDEDLa chiave è sospesa
CodiceSignificato
PLAN_UPGRADE_REQUIREDL’endpoint richiede un piano superiore o un pack add-on
PLAN_PACK_MISMATCHL’endpoint fa parte di un pack che la chiave non ha
SUBSCRIPTION_EXPIREDIl periodo pagato è terminato da più di 3 giorni. Nei primi 3 giorni dopo la scadenza le richieste vengono ancora servite secondo il piano e portano l’header X-Subscription-Grace-Ends. details contiene expired_at, grace_ended_at e renew_url
CodiceSignificato
RATE_LIMITLimite RPM superato. La risposta contiene l’header Retry-After: <sec>
CREDITS_EXHAUSTEDBudget mensile di crediti esaurito
SPEND_CAP_REACHEDRaggiunto il limite di spesa per gli endpoint AI
KEY_BUDGET_EXHAUSTEDLa chiave ha esaurito il proprio budget (credits_cap_cycle). L’account può comunque avere ancora crediti: il limite riguarda solo questa chiave
CodiceSignificato
INVALID_INPUTUno o più campi non hanno superato la validazione Zod. details è un array di { path, message }
INVALID_FIELDIl body contiene un nome di campo abbreviato invece di quello canonico. Vedi sotto
MISSING_FIELDSManca un campo obbligatorio
BAD_JSONJSON malformato nel body della richiesta

Esempio di 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" }
]
}
}

Gli endpoint delle carte accettano solo i nomi completi dei campi. Le forme abbreviate vengono rifiutate con 400, non lette in silenzio:

InviatoCampo canonicoCosa ci si aspetta
latlatitudegradi decimali, nord positivo
lng, lon, longlongitudegradi decimali, est positivo
tz con un numero, tzOffset, utcOffset, timezone_offsettimezoneOffsetnumero di ore da UTC, ad es. 5.75
tz con un nome, timeZone, time_zonetimezonenome di fuso IANA, ad es. Europe/Kyiv, oppure auto

La risposta elenca tutti i campi trovati in una sola volta, nell’ordine del body della richiesta, quindi la rinomina si fa in un unico passaggio:

{
"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 indica il percorso completo, quindi nella sinastria si vede di quale carta si tratta: chart1.lat, non semplicemente lat.

Lo stesso codice viene restituito quando timezone non si riesce a interpretare: valore vuoto, un’abbreviazione come EST (che è un -5 fisso tutto l’anno, quindi New York a luglio risulterà sbagliata di un’ora), un nome che non esiste nel database dei fusi orari, uno scostamento scritto come testo, tipo +03:00, oppure auto senza latitude e longitude. Il messaggio suggerisce cosa inviare invece, e path indica l’oggetto, ad esempio chart2.timezone.

Due cose da tenere presenti.

Non è una deprecazione. I nomi abbreviati non sono mai stati nel contratto e non comparivano in /openapi.json come campi del body. Fino al 2026-08-01 non funzionavano, ma venivano ignorati in silenzio: le coordinate hanno zero come default, quindi la carta veniva calcolata per 0°N 0°E in UTC. L’ascendente, le case e tutto ciò che ne deriva erano sbagliati, e la risposta non lo segnalava. Per questo le forme abbreviate non vengono riaccettate: due nomi per un solo campo per sempre, e in più tz è ambiguo (numero o nome di fuso).

Il point annidato è un’altra cosa. In /v1/acg-zones, /v1/acg/by-category, /v1/ccg-analysis e /v1/eclipse-analysis l’oggetto point: { lat, lng } usa nomi di campo dichiarati, e passano.

Il nome corretto del campo è metà del lavoro. Anche un body senza latitude e longitude dava 200, perché le coordinate avevano zero come default, e la risposta descriveva 0°N 0°E.

Fino al 2026-11-09 una richiesta del genere funziona, ma la risposta porta Deprecation: true, Sunset, Warning e il campo _warning nel body. Dal 2026-11-09 è un 400 INVALID_INPUT con latitude is required, in decimal degrees.

latitude: 0, longitude: 0 espliciti restano validi: il problema è il campo mancante, non il valore. timezoneOffset mantiene lo zero come default, perché lì zero significa UTC. city non sostituisce le coordinate: nessuno lo geocodifica. Il controllo si applica solo agli oggetti che portano contemporaneamente date e time.

CodiceSignificato
CALCULATION_ERRORL’input è valido, ma il motore non è riuscito a calcolare (ad esempio, una latitudine polare con Placidus). Prova Whole Sign / Equal o un’altra data.
CodiceHTTPSignificato
INTERNAL_ERROR500Errore imprevisto. Lo registriamo con lo stack trace, cita il request_id
GATEWAY_UNAVAILABLE / AI_UNAVAILABLE / LLM_UNAVAILABLE503Gateway AI non disponibile. Riprova con backoff esponenziale
QUEUE_UNAVAILABLE503Coda dei job in background non disponibile
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})` : ''}`);
}
}

Fai lo switch su code, non su message. Gli SDK ufficiali (@astroway/sdk, astroway) lanciano sottoclassi di errore tipizzate in base allo stato HTTP (AuthenticationError, RateLimitError, BadRequestError …), quindi il codice di gestione non dovrai scriverlo tu.

Per contattarci, invia a support@astroway.info:

  1. Il request_id dalla risposta (se è un 5xx)
  2. L’endpoint e il body JSON abbreviato (senza segreti)
  3. Comportamento atteso vs effettivo
  4. Fuso orario e ora approssimativa della richiesta (UTC)

La risposta arriva entro lo SLA del tuo piano (48 h Starter, 24 h Pro, personalizzato per Enterprise).

Utile?
Suggerisci modifica

Ultimo aggiornamento: