---
title: "Generate Bi Wheel"
method: POST
path: "/visualization/bi-wheel"
tags: ["visualization"]
---

# Generate Bi Wheel

`POST /visualization/bi-wheel`

## Request

- Base URL: `https://api.openephemeris.com`
- URL: `https://api.openephemeris.com/visualization/bi-wheel`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-OpenEphemeris-API-Key`
  - API key in header `X-API-Key`
  - API key in header `X-Service-Key`

Generate SVG/PNG bi-wheel chart. Free on every tier, including Explorer.

## Query parameters

- `format` string
- `size` integer
- `style` string
- `no_logo` boolean
- `aspect_grid` boolean
- `aspect_grid_orbs` boolean
- `include_angle_aspects` boolean
- `elements` boolean
- `planet_colors` boolean

## Request body

- BiWheelRequest: Bi-wheel visualization request. Each subject may carry birth params OR precomputed positions.
  - `configuration` NatalConfig: Declarative configuration for natal calculations.
    - `ascendant_on_left` boolean, nullable: When true (default), the Ascendant is placed at the 9 o'clock (West/left) position � matching the convention used by Astro.com, Solar Fire, and all major astrology software. Set to false to use the ecliptic-fixed (Aries-pinned) orientation instead.
    - `aspect_backing_discs` boolean, nullable: Wheel rendering only. When true (default), each aspect glyph sits on a small backing disc so it stays legible over crossing lines. Set false to draw bare glyphs. Honoured by /visualization/chart-wheel and /visualization/bi-wheel; rejected with 422 elsewhere.
    - `aspect_orbs` object: Caller-supplied orb allowances in degrees for the aspect lines drawn on the wheel, keyed by aspect name (conjunction, opposition, trine, square, sextile, and the minors quincunx, semisextile, semisquare, sesquiquadrate, quintile, biquintile). Same shape and semantics as ChartConfiguration.aspect_orbs: overrides the default table for the aspects named; aspects not named keep their defaults, and naming a minor is what turns it on. Setting an orb to 0 turns that aspect off entirely. An unknown aspect name is rejected with 422. Honoured by /visualization/chart-wheel and /visualization/bi-wheel (planet-to-planet lines; the include_angle_aspects lines keep their own table) and by /ephemeris/relocation (its aspect grid). /acg/midpoints, /ephemeris/natal/batch and /electional/natal-angle-crossings compute no aspect grid and reject the field with 422 rather than ignore it.
    - `asteroid_groups` AsteroidGroupEnum[]: Optional thematic asteroid groups to include alongside base object_set
    - `ayanamsa` 'lahiri' | 'fagan_bradley' | 'krishnamurti' | 'raman' | 'yukteshwar': Supported sidereal ayanamsa options. All five are computed from the same IAU 2006 general-precession model, so each is epoch-dependent rather than a frozen constant; they differ by up to ~2.3 degrees, which is enough to move a body across a sign boundary. Defaults to lahiri when zodiac_type is sidereal and no system is named.
    - `coordinate_frame` 'ecliptic' | 'equatorial' | 'horizontal': Reference frame for reported coordinates.
    - `coordinate_system` 'geocentric' | 'topocentric' | 'heliocentric' | 'barycentric': Coordinate system used for calculations.
    - `custom_objects` string[], nullable: Explicit body/point slugs to include, additive on top of object_set (and the entire set when object_set='custom'). Ephemeris bodies: sun, moon, mercury, venus, mars, jupiter, saturn, uranus, neptune, pluto, north_node, true_node, lilith, lilith_true, chiron, pholus, lilith_interpolated, eris, sedna, makemake, haumea, quaoar, orcus, ixion, varuna, cupido, hades, zeus, kronos, apollon, admetos, vulkanus, poseidon, eros, sappho, lilith_asteroid, nessus, chariklo, amor, betulia, icarus, apollo, adonis, phaethon, astraea, hebe, flora, metis, parthenope, victoria, egeria, irene, massalia, isis, anubis, odysseus, tolosa, medusa, ambrosia, aletheia, thule, polyxo, myrrha, valentine, hercynia, nestor, siva, atlantis, aphrodite, prometheus, epimetheus, shaposhnikov, lick, huya, ceres, pallas, juno, vesta, hygiea, eunomia, psyche, europa_asteroid, cybele, sylvia, thisbe, camilla, iris, davida, euphrosyne, interamnia. Angle-derived points: vertex, anti_vertex, south_node, part_of_fortune, equatorial_ascendant (alias east_point), equatorial_descendant. Unknown slugs are ignored.
    - `fixed_star_options` FixedStarConfig: Configuration for fixed star calculations.
      - `catalog_version` 'bright_mag3' | 'bright_mag5' | 'royal_stars' | 'parans_key': Fixed star catalog snapshots.
      - `include` boolean: Toggle fixed star conjunction calculations
      - `magnitude_limit` number: Maximum magnitude (lower = brighter)
      - `orb` number: Orb in degrees for fixed star hits
      - `stars` string[]: Optional whitelist of fixed stars to evaluate
    - `house_system` 'P' | 'K' | 'O' | 'R' | 'C' | 'E' | 'W': Supported house systems.
    - `node_source` 'true_osculating' | 'mean' | 'mean_apsides': Node/apsides calculation modes (SE §2.2).
    - `object_set` 'traditional_7' | 'modern_10' | 'modern_plus_chiron' | 'asteroids_major' | 'full' | 'custom': Standardized celestial object bundles.
    - `show_aspect_glyphs` boolean, nullable: Wheel rendering only. When true (default), an aspect glyph is drawn at the midpoint of each aspect line. Set false to draw the lines alone. Honoured by /visualization/chart-wheel and /visualization/bi-wheel; rejected with 422 elsewhere.
    - `zodiac_type` 'tropical' | 'sidereal': Supported zodiac frameworks.
  - `subject_a` WheelSubject, required: A wheel ring subject. Supply EITHER birth params (birth_datetime + birth_location, cast internally) OR a precomputed 'positions' array (rendered directly). When 'positions' is present, birth params are ignored for that subject.
    - `birth_datetime` DateTimeInput: Date/time input in ISO-8601, component, or Julian day form. A value that states a clock time must also state its zone, either as a suffix on the string or via the `timezone` field below.
      - `components` object: Date/time components (year, month, day, and optionally hour, minute, second). If hour/minute are present, pass `timezone` alongside them; without it the request is rejected with 400 ambiguous_datetime. Omit the clock entirely and the date resolves to 12:00 UTC.
      - `iso` string: ISO-8601 datetime (supported range 1550–2650 CE, JPL DE440). If it states a clock time it must carry its zone: either a 'Z'/±HH:MM suffix on the string ("1987-07-15T09:01:00-05:00"), or a `timezone` passed alongside it. A zone-less clock time is rejected with 400 ambiguous_datetime — it is not read as UTC. A date-only value ("1987-07-15") has no clock to be ambiguous about and resolves to 12:00 UTC.
      - `julian_day` number, double: Julian Day Number (always UTC-based, so it needs no zone)
      - `timezone` TimezoneInput: Timezone input using IANA names or UTC offsets.
        - `fold_preference` 'earlier' | 'later': Which occurrence to use when the naive local datetime falls in a fall-back fold (a repeated hour): 'earlier' (default — first occurrence) or 'later'. Only meaningful for naive datetimes; the response reports datetime_status=ambiguous_fold either way so the ambiguity can be surfaced to the user.
        - `iana_name` string: IANA timezone name
        - `time_standard` 'auto' | 'standard' | 'daylight': How to interpret a naive local datetime when this zone is applied. 'auto' (default): resolve through the historical-correction overlay where one covers the region/era, then IANA tzdata. 'standard': force the zone's standard (non-daylight) offset — for callers who KNOW the recorded time was standard time regardless of what tzdata believes. 'daylight': force standard+1h. Forcing either marks the resolution tz_confidence=client_override. Ignored when the datetime carries its own Z/±HH:MM suffix or when utc_offset is used.
        - `utc_offset` number: UTC offset in hours
    - `birth_location` BirthLocation: Location context for birth data: coordinates plus timezone.
      - `city` string: City name
      - `country` string: Country
      - `elevation` number: Elevation in meters. Accepted and echoed back unchanged; it does not affect planetary positions, which are computed geocentrically. Elevation changes results only where it is taken as the `elev` query parameter: /eclipse/solar/local (local circumstances) and /time/solar-event plus /ephemeris/agro/* (horizon rise/set times).
      - `latitude` CoordinateInput, required: Flexible coordinate input supporting multiple formats.
        - `components` object: Separate degree components with direction
        - `decimal` number: Decimal degrees (-90 to 90 for lat, -180 to 180 for lon)
        - `dms` string: Degrees, minutes, seconds string (e.g., '40°42'46"N')
      - `location_name` string: Birthplace display name (e.g. "Dallas, TX"). Never affects calculations — coordinates and timezone are the only location facts the engine reads. Echoed back verbatim where the response carries an echo block: as subject.location_name on chart routes that echo a subject (natal, draconic, progressed, synastry, natal-transits, overlay, natal/batch items, predictive transit-chart), inside search_summary on /electional/natal-angle-crossings, metadata on /acg/midpoints, and natal on /human-design/transit-chart. Omitted from the response when not sent.
      - `longitude` CoordinateInput, required: Flexible coordinate input supporting multiple formats.
        - `components` object: Separate degree components with direction
        - `decimal` number: Decimal degrees (-90 to 90 for lat, -180 to 180 for lon)
        - `dms` string: Degrees, minutes, seconds string (e.g., '40°42'46"N')
      - `region` string: State/region
      - `timezone` TimezoneInput, required: Timezone input using IANA names or UTC offsets.
        - `fold_preference` 'earlier' | 'later': Which occurrence to use when the naive local datetime falls in a fall-back fold (a repeated hour): 'earlier' (default — first occurrence) or 'later'. Only meaningful for naive datetimes; the response reports datetime_status=ambiguous_fold either way so the ambiguity can be surfaced to the user.
        - `iana_name` string: IANA timezone name
        - `time_standard` 'auto' | 'standard' | 'daylight': How to interpret a naive local datetime when this zone is applied. 'auto' (default): resolve through the historical-correction overlay where one covers the region/era, then IANA tzdata. 'standard': force the zone's standard (non-daylight) offset — for callers who KNOW the recorded time was standard time regardless of what tzdata believes. 'daylight': force standard+1h. Forcing either marks the resolution tz_confidence=client_override. Ignored when the datetime carries its own Z/±HH:MM suffix or when utc_offset is used.
        - `utc_offset` number: UTC offset in hours
    - `houses` WheelHouses: House geometry for a precomputed wheel ring. Required for the inner/single ring to draw houses and anchor orientation; the outer overlay ring does not require it.
      - `ascendant` number, required: Ascendant in degrees [0, 360). Used for ASC-pinned orientation.
      - `cusps` number[], required: 12 absolute-degree house cusps.
      - `house_system` string: House system code label (e.g. 'P').
      - `midheaven` number: Midheaven in degrees [0, 360).
    - `name` string: Optional display label for the ring.
    - `positions` PositionInput[]: Precomputed body positions. When present, the ring is rendered from these longitudes and birth params are ignored.
      - `body` string, required: Canonical lowercase body key (e.g. 'sun', 'moon', 'north_node'). Unknown keys render with a generic marker and the key as label.
      - `longitude` number: Ecliptic longitude in degrees [0, 360).
      - `retrograde` boolean: Explicit retrograde flag. Defaults to speed < 0 when speed is given, else false.
      - `speed` number: Longitudinal speed in deg/day. When present and negative (and 'retrograde' is omitted), the body is treated as retrograde.
  - `subject_b` WheelSubject, required: A wheel ring subject. Supply EITHER birth params (birth_datetime + birth_location, cast internally) OR a precomputed 'positions' array (rendered directly). When 'positions' is present, birth params are ignored for that subject.
    - `birth_datetime` DateTimeInput: Date/time input in ISO-8601, component, or Julian day form. A value that states a clock time must also state its zone, either as a suffix on the string or via the `timezone` field below.
      - `components` object: Date/time components (year, month, day, and optionally hour, minute, second). If hour/minute are present, pass `timezone` alongside them; without it the request is rejected with 400 ambiguous_datetime. Omit the clock entirely and the date resolves to 12:00 UTC.
      - `iso` string: ISO-8601 datetime (supported range 1550–2650 CE, JPL DE440). If it states a clock time it must carry its zone: either a 'Z'/±HH:MM suffix on the string ("1987-07-15T09:01:00-05:00"), or a `timezone` passed alongside it. A zone-less clock time is rejected with 400 ambiguous_datetime — it is not read as UTC. A date-only value ("1987-07-15") has no clock to be ambiguous about and resolves to 12:00 UTC.
      - `julian_day` number, double: Julian Day Number (always UTC-based, so it needs no zone)
      - `timezone` TimezoneInput: Timezone input using IANA names or UTC offsets.
        - `fold_preference` 'earlier' | 'later': Which occurrence to use when the naive local datetime falls in a fall-back fold (a repeated hour): 'earlier' (default — first occurrence) or 'later'. Only meaningful for naive datetimes; the response reports datetime_status=ambiguous_fold either way so the ambiguity can be surfaced to the user.
        - `iana_name` string: IANA timezone name
        - `time_standard` 'auto' | 'standard' | 'daylight': How to interpret a naive local datetime when this zone is applied. 'auto' (default): resolve through the historical-correction overlay where one covers the region/era, then IANA tzdata. 'standard': force the zone's standard (non-daylight) offset — for callers who KNOW the recorded time was standard time regardless of what tzdata believes. 'daylight': force standard+1h. Forcing either marks the resolution tz_confidence=client_override. Ignored when the datetime carries its own Z/±HH:MM suffix or when utc_offset is used.
        - `utc_offset` number: UTC offset in hours
    - `birth_location` BirthLocation: Location context for birth data: coordinates plus timezone.
      - `city` string: City name
      - `country` string: Country
      - `elevation` number: Elevation in meters. Accepted and echoed back unchanged; it does not affect planetary positions, which are computed geocentrically. Elevation changes results only where it is taken as the `elev` query parameter: /eclipse/solar/local (local circumstances) and /time/solar-event plus /ephemeris/agro/* (horizon rise/set times).
      - `latitude` CoordinateInput, required: Flexible coordinate input supporting multiple formats.
        - `components` object: Separate degree components with direction
        - `decimal` number: Decimal degrees (-90 to 90 for lat, -180 to 180 for lon)
        - `dms` string: Degrees, minutes, seconds string (e.g., '40°42'46"N')
      - `location_name` string: Birthplace display name (e.g. "Dallas, TX"). Never affects calculations — coordinates and timezone are the only location facts the engine reads. Echoed back verbatim where the response carries an echo block: as subject.location_name on chart routes that echo a subject (natal, draconic, progressed, synastry, natal-transits, overlay, natal/batch items, predictive transit-chart), inside search_summary on /electional/natal-angle-crossings, metadata on /acg/midpoints, and natal on /human-design/transit-chart. Omitted from the response when not sent.
      - `longitude` CoordinateInput, required: Flexible coordinate input supporting multiple formats.
        - `components` object: Separate degree components with direction
        - `decimal` number: Decimal degrees (-90 to 90 for lat, -180 to 180 for lon)
        - `dms` string: Degrees, minutes, seconds string (e.g., '40°42'46"N')
      - `region` string: State/region
      - `timezone` TimezoneInput, required: Timezone input using IANA names or UTC offsets.
        - `fold_preference` 'earlier' | 'later': Which occurrence to use when the naive local datetime falls in a fall-back fold (a repeated hour): 'earlier' (default — first occurrence) or 'later'. Only meaningful for naive datetimes; the response reports datetime_status=ambiguous_fold either way so the ambiguity can be surfaced to the user.
        - `iana_name` string: IANA timezone name
        - `time_standard` 'auto' | 'standard' | 'daylight': How to interpret a naive local datetime when this zone is applied. 'auto' (default): resolve through the historical-correction overlay where one covers the region/era, then IANA tzdata. 'standard': force the zone's standard (non-daylight) offset — for callers who KNOW the recorded time was standard time regardless of what tzdata believes. 'daylight': force standard+1h. Forcing either marks the resolution tz_confidence=client_override. Ignored when the datetime carries its own Z/±HH:MM suffix or when utc_offset is used.
        - `utc_offset` number: UTC offset in hours
    - `houses` WheelHouses: House geometry for a precomputed wheel ring. Required for the inner/single ring to draw houses and anchor orientation; the outer overlay ring does not require it.
      - `ascendant` number, required: Ascendant in degrees [0, 360). Used for ASC-pinned orientation.
      - `cusps` number[], required: 12 absolute-degree house cusps.
      - `house_system` string: House system code label (e.g. 'P').
      - `midheaven` number: Midheaven in degrees [0, 360).
    - `name` string: Optional display label for the ring.
    - `positions` PositionInput[]: Precomputed body positions. When present, the ring is rendered from these longitudes and birth params are ignored.
      - `body` string, required: Canonical lowercase body key (e.g. 'sun', 'moon', 'north_node'). Unknown keys render with a generic marker and the key as label.
      - `longitude` number: Ecliptic longitude in degrees [0, 360).
      - `retrograde` boolean: Explicit retrograde flag. Defaults to speed < 0 when speed is given, else false.
      - `speed` number: Longitudinal speed in deg/day. When present and negative (and 'retrograde' is omitted), the body is treated as retrograde.

## Response `200`

Successful Response

## Other responses

- `403`: Forbidden (tier upgrade required)
- `422`: Validation Error

---

[API](https://skmtc.dev/openephemeris/apis/open-ephemeris-api.md) · [All operations](https://skmtc.dev/openephemeris/apis/open-ephemeris-api/llms.txt) · [OpenAPI document](https://skmtc.dev/openephemeris/apis/open-ephemeris-api/revisions/d195a769cb89?raw)
