AstroWay/api v2.325.2 · hi
सभी सिस्टम सामान्य हैं

// product · release notes

Changelog what is new

Only changes that affect integrator code: new endpoints, SDK releases, /openapi.json schema changes, credit price changes, deprecations, breaking changes. Newest first.

Latest · v2.325.2 Endpoints · 865 CI tests · 888 API contract · v1 stable · 12-mo deprecation

2026-10-05 · Solar Return of the year you ask for, Lunar Return strictly after, and both return the moment

Fix. For a birthday between 1 December and 5 January, POST /v1/solar-return returned the neighbouring year’s return in about half of all years: a 15 December birthday with year: 2026 got 14 December 2025. The return now always belongs to the requested year; for a 1 January birthday the moment may fall on 31 December of the previous year in UTC. POST /v1/lunar-return could return a moment a few hours before afterDate when the previous return was very close; the result is now always later.

If you stored solar returns for December and early January birthdays, recompute them.

New fields. Both endpoints return returnMoment, the moment of the return as ISO 8601 UTC to the second, so you no longer convert julianDay yourself:

"returnMoment": "2027-05-10T07:43:11Z"

POST /v1/davison returns midpoint with the moment and place the chart is built for, and the mean longitude now takes the shorter arc: Tokyo and Honolulu give 170.915, not -9.085.

"midpoint": { "utc": "1991-06-30T22:30:00Z", "lat": 28.495, "lng": 170.915 }

2026-10-04 · @astroway/ui web components (alpha)

A new package, @astroway/ui: natal wheel, aspect grid, planet table, moon phase, planet of the day, horoscope, tarot, sign compatibility, synastry and Chinese sign as plain HTML elements. One <script> tag from a CDN or npm install @astroway/ui; works in HTML, WordPress, Vue, Svelte, React 19 and Next.js.

What to do with your code. Nothing if you draw charts yourself. If you want a ready element: pass data from your server through data, use the public elements with no key, or give a site’s pk_ key in api-key. Alpha: attribute names may still change before 1.0. Details: Web components.

2026-10-04 · A browser key is created only with a budget and a scope

POST /v1/keys with origin_restriction.type: "public" (a pk_ key) now requires two fields besides the origin list: credits_cap_cycle (how many credits the key may spend per cycle, 0 parks it) and allowed_endpoints (which paths it may call). Without either the request returns 400. PATCH /v1/keys/{id} no longer lets a pk_ key lose either one (null returns 400), and a pk_ key missing its budget or scope is refused with 403 PUBLISHABLE_KEY_UNBOUNDED.

What to do with your code. If you create pk_ keys from a script, add credits_cap_cycle and allowed_endpoints to the body. Server keys are not affected; credits_cap_cycle can now also be passed when creating any key. No active pk_ key lacked these fields when this changed, so nothing already issued broke.

2026-10-02 · Localized names in public responses

GET /v1/public/moon-phase and GET /v1/public/planet-of-day now return a localized object that follows ?lang= or Accept-Language. The English fields are unchanged.

What to do with your code. Nothing, if you match on the English values: they are still there and still the stable identifiers. If you kept your own translation maps for signs, planets, weekdays or moon phases, you can drop them and read localized instead.

The names come from an explicit terminology table rather than machine translation. That is not cosmetic: under the previous scheme the moon phase was translated word-for-word, and every language had been serving a finance term in place of the astronomical one. The same fix reaches the /v1/embed/* widgets.

Open sets stay English and are documented as such: themes[] on planet of the day, tarot card names and meanings.

2026-10-01 · Human Design returns localised names

POST /v1/public/human-design now returns an extra localized block that follows ?lang= and Accept-Language, the way /public/moon-phase and /public/planet-of-day already do.

"localized": {
"type": "Generador",
"strategy": "Espera la respuesta sacral",
"authority": "Emocional (plexo solar)",
"centers": { "SolarPlexus": "Plexo solar", "Spleen": "Bazo" },
"defined": "definido",
"open": "abierto"
}

The English fields are unchanged: type, strategy, authority and the centre names stay the identifiers you match on. Centres inside localized are keyed by that same identifier (SolarPlexus, not a translated name), so your matching does not depend on the language.

Available in 21 languages.

2026-09-30 · Static natal texts, and a site key for WordPress

GET /v1/natal-texts?keys=sun.aries,moon.h4,sun_moon.trine&lang=en returns edited interpretation texts, up to 64 keys per call, for the price of one ordinary call. Nothing is generated at request time. Planet in sign is ready in 20 languages; planet in house and aspects are added as they are written. A key that has no text in the requested language comes back in missing, never in another language.

POST /v1/site-keys issues a key to a WordPress site that proves it controls its domain. The key works only for that domain, on a set of free readings, 300 calls an hour.

A site owner can move the site onto their account’s key in one click: the /dashboard/connect page returns a one-time code to the admin, and the site’s server exchanges it at POST /v1/site-keys/connect/exchange for the account key. The site key stops working 24 hours after the exchange.

What to do with your code. Nothing, if you do not need either. If you show natal charts, the texts are now available without AI and without a price per text.

2026-09-28 · The DPA is accepted with a button, and three new endpoints around it

GET /v1/me/dpa says which version of the agreement is current and whether your account has accepted it. POST /v1/me/dpa/accept accepts it. GET /v1/me/dpa.pdf returns a PDF with the acceptance record printed in it: account, version, date and time. All three take the account’s Bearer token and cost no credits.

What to do with your code. Nothing, if you do not need a DPA. If your lawyer requires one: read the text at /legal/dpa/, accept it in the dashboard or with this endpoint, and download the PDF. The page used to promise a signed copy within five business days, and there was nobody to sign it; Article 28(9) GDPR accepts the contract “in writing, including in electronic form”, so the acceptance record is that form.

One clarification worth reading by a lawyer in particular. The data is stored and computed in Nuremberg, but we administer those machines from Ukraine. Chapter V of the GDPR treats remote access as a transfer to a third country even when nothing is copied, so section 6 of the agreement names it plainly and refers to the Standard Contractual Clauses, instead of the “no cross-border transfer” wording the page carried before, which was not true.

2026-09-27 · Panchang: yoga is computed from sidereal longitudes

POST /v1/vedic/panchang/yoga, POST /v1/vedic/panchang/full and every POST /v1/vedic/muhurat/* computed the yoga from the tropical longitudes of the Sun and Moon. A yoga is the sum of the two longitudes, so the ayanamsa enters it twice, and the result was about four yogas out of 27 off. The longitudes are now sidereal, with the ayanamsa from the request (Lahiri by default). For Kyiv on 2026-09-21 the answer matches drikpanchang: Shobhana until 13:36, then Atiganda.

What to do with your code. If you stored yoga or muhurat windows, recompute them: yoga.number, yoga.name and sumLongitude change, and in muhurat results so do the set and order of windows, because the yoga is part of the score. Tithi, karana, nakshatra and vara are unchanged.

Two charts are fixed in the same release. /v1/embed/kundli placed sidereal grahas in a tropical lagna, so every house was one sign off. /v1/render/wheel-vedic-north, -south and -east with zodiacType: "sidereal" now move the houses into the sidereal zodiac too, not only the planets.

2026-09-26 · MCP by domain: one subject instead of 782 tools

https://mcp.astroway.info/mcp/<domain> serves one subject out of fourteen: core, vedic, chinese, hellenistic, tarot, numerology, human-design, forecast, relationships, psychological, divination, applied, reports, platform.

What to do with your code. Nothing, if the full catalogue suits you: /mcp has not changed and still serves all 782 tools. If your agent works on one subject, change the URL in the client configuration to the domain: the tools/list response drops from 2.9 MB to 107-970 KB, and the agent reads less before it picks a tool.

Balance checks and cost estimates are in every domain, because an agent limited to one subject still needs to know what a call costs.

GET /domains returns the list as JSON, no key needed. An unknown domain is a 404 listing the real ones, not a silent return of the whole catalogue.

2026-09-25 · Unknown birth time: a chart without invented houses and angles

POST /v1/chart and POST /v1/synastry accept timeUnknown: true in place of time. In that mode you get planets and aspects, while houses, houseAspects, chartSect and siderealTime come back as null.

What to do with your code. Nothing, if you always know the birth time: without the flag time stays required and the response is unchanged. If you have been filling in an assumed noon for users who do not know their time, switch to timeUnknown: true and stop showing an ascendant that nobody actually computed.

The chart comes with a timeUnknown block: the assumed instant (local noon), the list of omitted fields, and the Moon’s longitude at the start and end of the day. The Moon covers 11.8 to 15.4 degrees per day and can change sign, so the block carries the arc, the signs it occupied and a changesSign flag. Aspects involving the Moon are unreliable in this mode, which is what moonAspectsUncertain says.

Every other endpoint refuses the flag with 400 TIME_UNKNOWN_UNSUPPORTED. Transits, progressions, directions, profections and synastry house overlays are built from angles or houses, so without a birth time there is nothing to return.

2026-09-24 · Compact responses: fields and precision on every endpoint

Two query parameters trim the response at the last step. fields is a comma-separated list of paths relative to data, applied to every element of an array: planets.name means the name of every planet. precision is an integer from 0 to 15 that rounds every non-integer number and leaves integers alone.

What to do with your code. Nothing, if you read the whole response: without these parameters nothing has changed. If you pass the response to a model, try them: POST /v1/chart with ?fields=planets.name,planets.longitude&precision=2 is 778 bytes instead of 32,410.

A path that matched nothing comes back in _fields_unmatched rather than vanishing. Optional fields really are absent from some responses, so that is not an error. But a list in which no path matched at all returns 400 FIELDS_UNKNOWN with the list: an empty object in place of a chart would be a confident wrong answer.

Both parameters are in /openapi.json on all 770 operations, so SDK generators pick them up on their own. They are deliberately in the query, not a header: the response cache is keyed on the query, and a mode in a header would hand a compact response to someone who asked for the full one.

2026-09-24 · Step fields are bounded on three endpoints

Three fields that divide a range into steps are bounded now and answer 400 instead of accepting a value the request never finishes on:

  • POST /v1/rectification: stepMinutes from 0.5 to 240, searchRangeMinutes up to 1440, orb up to 15. The quotient is checked as well: more than 1440 candidate charts in one request is refused.
  • POST /v1/aspect-timeline and POST /v1/aspect-bar: stepDays from an hour to a year, maxOrb up to 30, and no more than 5000 ephemeris points per request.

In the same place, weight on a rectification event must now be greater than zero and at most 3, and type accepts only the values in its list. An event sent without a weight used to leave score: null on every candidate.

Lists in the request body are bounded too, because they are loop counts:

  • planet1Ids, planet2Ids, visiblePlanetIds, planetIds and transitPlanetIds take at most 32 entries, each a non-negative integer. /v1/aspect-timeline multiplies two of those lists by the aspect list and by the range, so an unbounded pair was a multiplication with no ceiling.
  • aspectAngles takes at most 64 angles, each within 0..360. An angle outside that range could not match anything and returned an empty result rather than a 400.
  • events on rectification takes at most 20, and parts on arabic parts at most 64.

POST /v1/retrograde no longer repeats a scan: a duplicated planet id used to run the whole multi-year pass again and return each retrograde twice.

Observer coordinates are bounded where an endpoint declares its own pair: point on /v1/eclipse-analysis and /v1/ccg-analysis, and latitude and longitude on /v1/vedic/kp/horary. Latitude 500 used to answer 200 with eclipse visibility and a path-of-totality verdict for a place that does not exist. In the same pass, year on /v1/moon-aspects is bounded to the years a date can express at all.

If your code sends any of these outside the bounds it will get a 400 naming the field in error.details, instead of an answer you cannot rely on.

2026-09-23 · /v1/horoscope/compatibility takes zodiac signs only

sign1 and sign2 are now one of twelve values, aries to pisces, an enum in /openapi.json. Case and surrounding spaces do not matter: Aries and LEO are accepted.

What to do with your code. Nothing, if you send English sign names. Anything else used to reach the model as it was and came back as text about an invented pairing; it is now a 400 naming the field.

2026-09-22 · /v1/reports/generate costs what the report it builds costs

The report dispatcher charged 10 credits whatever the report_type. It now charges the price of the target report: natal is 5000, tarot is 100, and so on for all twelve types. Exactly the same as calling /v1/reports/natal directly.

What to do with your code. Recalculate your budget if you go through the dispatcher: the same number of calls now costs what the direct paths cost, not five hundred times less. The response, schema and headers have not changed; only the number in X-Credits-Used has.

The dispatcher no longer passes on the Free plan. The plan gate was read from the endpoint’s price, and that price was understated, so PDF reports opened where the plan does not include them. The gate now comes from the target report, and the call returns 402 PLAN_UPGRADE_REQUIRED, like the direct path. The same applies to the sandbox and to packs.

This corrects a promise rather than changing a policy: the dispatcher announcement of 2026-05-15 said a call through report_type costs exactly what the direct one does. For four months that was not true, and the /credits/ page no longer prints a single number next to an endpoint whose price depends on the request body.

2026-09-21 · Documentation as an MCP server, no key

https://mcp.astroway.info/mcp/docs answers without authorisation, because none of its tools spends a credit.

  • find_endpoint searches all 770 operations and returns, for each, the method, the URL, the credit cost, the tier, the required body fields and a link to its reference page. 700 carry a price and 37 more are marked as keyless.
  • search_docs searches 281 guide pages, Ukrainian and English.
  • read_doc returns one page as markdown.
  • list_docs shows the whole index by section.

What to do with your code. Nothing. It is a new address beside the existing ones and no configured client changes. If you are choosing endpoints for an agent, a workflow can now be costed before a key exists.

2026-09-21 · MCP tools take fields and precision, and stop sending the data twice

Every tool on mcp.astroway.info now takes two parameters on top of its own: fields, a comma-separated list of dotted paths relative to data, and precision, the number of decimal places to keep. They are the same two parameters REST takes, and they reach the API on the same query string.

What to do with your code. Nothing, if the whole response suits you. If your agent reads two columns off a chart, name them: a natal chart over MCP weighed 91,737 bytes, and 1,182 with three paths and precision: 2. The credits are identical; the difference is paid by whoever reads the answer.

The text block in a tool result is no longer indented. It still repeats what the structured output carries, because older clients need it, but the indentation alone measured 13,313 bytes on one chart.

Fixed: sixty reference tools answered 404. They called GET endpoints with POST, so all twenty-four tarot decks, the zodiac and esoteric tables, /acg/categories, /muhurta/types and /kabbalah/shem-names answered 404 NOT_FOUND from the day they were registered. The same tools worked in the stdio package @astroway/mcp. Twenty more tools with a path parameter never substituted it into the URL. Both are fixed, and nothing changes in your code.

2026-09-21 · timezone: send a zone name and the offset for that date is worked out

Every request that takes timezoneOffset now also takes timezone: an IANA name such as Europe/Kyiv, or auto to look the zone up from latitude and longitude. The server takes the offset those clocks kept at that local date and time, summer time included, and uses it in place of timezoneOffset.

What to do with your code. Nothing, if you already send a correct offset. If you have been computing offsets yourself, you can send the zone instead. When both fields arrive, timezone wins, so an SDK model that always sends timezoneOffset: 0 does not get in the way.

Why it matters: the offset is easy to get wrong by an hour. Kyiv on 1990-05-15 kept Moscow summer time, UTC+4, not +3, and leaving the offset out still means UTC.

A clock time that happened twice, when clocks went back, takes the first occurrence; one that never happened, when they went forward, takes the offset from before the change. Abbreviations such as EST are refused with 400 INVALID_FIELD, because EST is a fixed -5 all year. Before 1970 the tz database is not reliable for every place, so for older births with a known local clock send timezoneOffset.

timeZone, time_zone, and tz carrying a name now point at timezone in the INVALID_FIELD message rather than at timezoneOffset.

2026-09-18 · The spec no longer asks for a key where none is needed

Thirty-seven operations answer without a key: nine under /v1/public/*, fourteen under /v1/embed/* and fourteen reference lookups under /v1/reference/*. In openapi.json, twenty-eight of them inherited the document-level ApiKeyAuth, so the document claimed a credential was required while every one of those routes is mounted ahead of the auth check and has always answered anonymously.

What to do with your code. Nothing, if you already call them without a key: the behaviour has not changed and is not changing. If you generate a client from the spec, regenerate it: these operations stop requiring a credential, and security: [] is now stated explicitly.

The same fix corrects the documentation pages, which told the reader to send a key, and their markdown twins, which were dropping the example call.

2026-09-18 · Bhava Bala: strength of the twelve houses

POST /v1/vedic/bhavabala. Shadbala gave you planetary strength but not house strength. Bhava Bala is its direct companion from the same BPHS chapter.

What to do with your code. Nothing, unless you compute house strength. If you were assembling it yourself on top of /vedic/shadbala/full, it is one call now, and the house lord’s strength comes from the same code /shadbala/full runs, so the two answers cannot disagree.

Each house returns its three components separately: Bhavadhipati Bala (the lord’s Shadbala), Bhava Digbala (the class of the sign on the house midpoint and the direction it is strong in) and Bhava Drishti Bala (the net aspect balance). Plus the total in virupas and rupas, a rank, and the strongest and weakest house.

The endpoint is marked yellow: it inherits the status of Shadbala, whose aspect model is simplified to whole-sign. Digbala and the sign classes are exact by construction.

2026-09-17 · Public endpoints report both rate-limit counters, not just the tightest

A call to /v1/public/* carrying X-AstroWay-Site-URL is measured against two counters at once: 300 an hour for the declared site, and a 600 an hour ceiling for the address. The standard X-RateLimit-* headers describe only the tightest of the two, so the other one was invisible. The response carries both now:

X-RateLimit-Scope: site
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 297
X-RateLimit-Counters: ip=597/600, site=297/300

The format is scope=remaining/limit, comma separated. It is sent only when there really are two counters: an anonymous call carrying X-AstroWay-Site-URL. A call with a paid key is counted against the key at your plan’s rate, where there is one counter and no header. It is on the 429 response too, where it matters most.

The limits are unchanged. What changed is how much of them you can see.

What to do with your code. If you render several domains server-side from one address, read X-RateLimit-Counters rather than X-RateLimit-Remaining alone: each domain gets its own site bucket, the IP ceiling is shared across all of them, and it is the one that binds.