For developers and AI agents

Charts, data, and embeds.

Also here, without an account or a key: shared sky data as plain JSON files, and the support matrix — runtime requirements, the runtimes actually tested and known limits — worth reading before you choose an integration.

The optional ownership SDK is a separate, read-only integration for registry verification and public ownership reads. Charts, sky data, and widgets do not require it or a wallet.

Shared sky data

The computed dates behind this site's calendars — today's sky, the weeks ahead, retrograde windows, stations, sign ingresses, moon phases, eclipses, and exact aspects — are published as versioned JSON. The files are static, cached at the edge, and open to any origin. There is no key or signup. These files contain no personal birth data: they describe the shared sky, and the site's own chart calculation stays on the device.

Quick start

One request returns today's sky. No key, no account:

curl --fail --silent --show-error https://zodiacs.org/api/v1/sky/today.json

The payload opens with a summary you can read straight out, and names the edition it was computed for in date and snapshotAt. Editions change daily and delivery can be delayed, so read those fields rather than assuming the file you hold is current. Before noon, a snapshot describes positions computed for later that day.

In JavaScript, with the checks worth keeping in production:

const response = await fetch('https://zodiacs.org/api/v1/sky/today.json', {
  cache: 'no-cache',
  signal: AbortSignal.timeout(10_000),
});
if (!response.ok) throw new Error(`Sky request failed: HTTP ${response.status}`);

const sky = await response.json();
if (sky?.schema !== 'zodiacs.sky-api.today.v1'
  || typeof sky.date !== 'string'
  || typeof sky.snapshotAt !== 'string'
  || typeof sky.summary !== 'string'
  || !Array.isArray(sky.bodies)
  || sky.bodies.length === 0
  || sky.bodies.some((body) => !body
    || typeof body !== 'object'
    || typeof body.body !== 'string'
    || typeof body.position !== 'string'
    || typeof body.retrograde !== 'boolean')) {
  throw new Error('Unexpected sky payload');
}

const today = new Date().toISOString().slice(0, 10);
if (sky.date !== today) {
  throw new Error(`Sky edition ${sky.date} is not current (${today} UTC)`);
}
if (sky.snapshotAt !== `${sky.date}T12:00:00.000Z`) {
  throw new Error('Unexpected sky snapshot time');
}

console.log(`Computed positions for ${sky.snapshotAt}`);
console.log(sky.summary);
for (const body of sky.bodies) {
  console.log(body.body, body.position, body.retrograde ? 'Rx' : '');
}

This one checks the payload kind, the fields it uses, and the current UTC edition before displaying the computed snapshot.

Sky data for AI agents

Every payload is self-describing. It opens with a summary — one or two plain sentences that state the file's facts, ready to quote — and carries an about block that defines each field and its units, a $schema link to its JSON Schema, and links to the related files. Raw numbers come with formatted twins (lon alongside position, illumination alongside illuminationPercent), and every event carries a label such as "Mercury retrograde in Scorpio, October 24, 2026 – November 13, 2026".

An agent should start at /api/v1/llms.txt: it lists every endpoint, defines every field, states the caveats worth repeating, and maps common questions ("Is Mercury retrograde?", "When is the next full moon?", "When does the Sun enter Libra?") to the file and field that answer them. Tool-calling frameworks can load /api/v1/openapi.json directly, and the daily files have Markdown twins for readers that fetch pages as text.

Daily endpoints

Yearly endpoints

Documents and schemas

The contract

Positions are apparent geocentric tropical longitudes from the same engine the calculators use, tested against NASA JPL Horizons reference data at two dates, 1907 and 2020, where the largest difference is 14.8 arcseconds. Today's positions are a single snapshot taken at 12:00 UTC (snapshotAt). Publication is scheduled from 00:00 UTC; jobs, deployment, or caches can delay availability. All instants are UTC in ISO 8601, and signs are lowercase slugs with an English signName beside them.

A retrograde window's from and to are its stations unless clippedStart or clippedEnd is true, which means the data boundary truncated the window and the real station lies outside coverage. Within v1, fields are added, never renamed or removed; a breaking change would ship under /api/v2/ and v1 would keep working. Yearly files are byte-stable between data refreshes, so conditional requests are cheap. Year files cover 2026–2030 today and grow as the underlying data is extended; read index.json rather than assuming which years exist.

Freshness and caching

Check the file you consume: date identifies the UTC edition for today's sky, planet files, and signs; snapshotAt is its noon snapshot. Upcoming events use from as the snapshot instant. generatedAt records the file build time and can change without a new edition. The index's coverage.dailyDate describes the index; separately cached files can have different dates. Label an older edition by its date or wait for a current one before presenting it as today's sky.

Current cache lifetimes are 300 seconds for sky/today.json, 3,600 seconds for index.json, and 86,400 seconds for the remaining API files, including upcoming events, planets, signs, and Markdown twins. Revalidation can refresh a cached response; always check its edition date as well. Yearly files remain byte-stable between data refreshes.

License and attribution

The data is free to use under CC BY 4.0. Credit "Zodiacs.org" with a link to https://zodiacs.org wherever the data is shown.

Widgets and feeds

If you would rather embed a finished surface than consume JSON, the embeddable widgets render tonight's moon, today's sky, and a mini birth chart inside a sandboxed iframe. Dated editorial is available as RSS: daily horoscopes and the daily sky. The site-wide guide for agents is llms.txt.

Embed today's sky

The same daily edition as /api/v1/sky/today.json, as a finished card: one iframe, no script on your page, and the theme and accent parameters are applied inside the frame. The card links back to zodiacs.org, which is the attribution.

<iframe src="https://zodiacs.org/embed/sky/?theme=dark" title="The sky today — Zodiacs.org" width="480" height="250" style="border:0;border-radius:14px;overflow:hidden;max-width:100%" loading="lazy" sandbox="allow-scripts allow-forms allow-same-origin allow-popups allow-popups-to-escape-sandbox" referrerpolicy="strict-origin-when-cross-origin"></iframe>