API Versioning
AstroAPI versions breaking changes with a compatibility date instead of a version number in the URL. The endpoint paths never change; you pin a date, and you keep receiving exactly the behaviour that was current on that date.
Your Version
Send the compatibility date you built against in the X-Api-Version header:
GET /api/modules HTTP/1.1
Host: api.astroapi.cloud
X-Api-Key: your_api_key
X-Api-Version: 2026-01-01Every response tells you which version was applied:
X-Api-Version: 2026-01-01
Vary: X-Api-VersionIf you send no header, requests use your organization's pinned version, and if you have not pinned one, the baseline of 2026-01-01. New behaviour is never applied to you automatically — an integration written today keeps working unchanged no matter what we ship later.
Changelog
Each breaking change is listed here with the date it takes effect. Pinning a date gives you every change on or before it.
| Date | Change |
|---|---|
| — | No breaking changes yet. All versions currently behave identically to the 2026-01-01 baseline. |
The baseline 2026-01-01 is the oldest version we serve. Pinning an earlier date is accepted and resolves to the baseline.
Pinning Your Organization
Rather than adding a header to every call, pin your organization once. All unversioned requests then use that date.
curl -X PATCH "https://api.astroapi.cloud/api/org/api-version" \
-H "Content-Type: application/json" \
-H "X-Api-Key: your_api_key" \
-d '{
"data": {
"type": "organizations",
"attributes": { "apiVersion": "2026-01-01" }
}
}'Read back the current pin, along with the range you can choose from:
curl "https://api.astroapi.cloud/api/org/api-version" \
-H "X-Api-Key: your_api_key"{
"data": {
"type": "organizations",
"id": "org_123",
"attributes": {
"apiVersion": "2026-01-01",
"effectiveApiVersion": "2026-01-01",
"baselineApiVersion": "2026-01-01",
"latestApiVersion": "2026-01-01"
}
}
}Send "apiVersion": null to clear the pin and fall back to the baseline.
Upgrading Safely
The header always wins over the organization pin, which makes a safe rollout possible:
- Read the changelog above and check which changes fall between your current date and the new one.
- Send the new date in
X-Api-Versionon a few requests, or in your staging environment, and verify the responses. - When you are satisfied, pin your organization to the new date and drop the header again.
Because the header overrides the pin per request, you can also do the reverse: pin your organization forward and temporarily send an older date from a service you have not migrated yet.
Browser and Embed Clients
Contexts that cannot set request headers — <img>, <iframe> and <script> embeds, signed chart URLs — accept the date as a query parameter instead:
https://api.astroapi.cloud/api/chart/image.svg?api_version=2026-01-01&...The header takes precedence when both are present. For fetch() and XHR, use the header; X-Api-Version is allowed by CORS and exposed on responses, so you can read back which version was applied.
Validation
A malformed value returns 400 Bad Request rather than quietly falling back:
{
"errors": [{
"status": "400",
"title": "Bad Request",
"detail": "Invalid X-Api-Version: \"v2\". Expected a date in YYYY-MM-DD format."
}]
}The value must be a real calendar date in YYYY-MM-DD form. A well-formed date outside the supported range is clamped rather than rejected: earlier than the baseline resolves to the baseline, later than the newest change resolves to the newest behaviour.
Caching
Responses are marked Vary: X-Api-Version, so a shared cache or CDN in front of your integration will keep versions apart. If you cache API responses yourself, include the compatibility date in your cache key.
What Counts as a Breaking Change
Changes that get a date and appear in the changelog:
- Removing or renaming a field in a response
- Changing the type or shape of an existing field
- Making an optional field required, or an omitted field always present
- Changing the meaning of an existing value
- Removing an endpoint or changing its semantics
Changes that ship without a version, because they cannot break a correct client:
- Adding a new endpoint
- Adding a new optional request parameter
- Adding a new field to a response
- Adding a new value to an enum you only read
- Bug fixes that bring behaviour in line with documentation
Write your integration to ignore unknown response fields. Additive changes arrive on every version, including yours.