Astronomy API v3

Version 3 of the Astronomy API, published by the provider as a reference draft with a complete OpenAPI 3.1 definition before it ships — "so that the design can be read and argued with". A breaking redesign of the v2 request and response shapes: JSON numbers instead of strings, one representation per value, a declared meta.units block, ISO 8601 instants with an explicit sampling step and timezone, cursor pagination on positions, RFC 9457 problem details, bearer authentication, and apsis events alongside eclipses. Five operations across positions, events, search and the two studio renderers. NOT YET IN PRODUCTION — /api/v2 remains the callable surface.

Operations 5

GET /positions Positions of one or more bodies over a span of time #
GET /events Eclipses and apsides for the observer's location #
POST /studio/star-chart Render a star chart #
POST /studio/moon-phase Render the Moon's phase #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/astronomy-api-v3"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

astronomy-api-v3-openapi.yaml Raw ↑
openapi: 3.1.0

info:
    title: AstronomyAPI
    version: '3.0'
    summary: Positions and events for the Sun, the Moon and the planets.
    description: |
        Version 3 is a breaking redesign of the v2 contract. The changes it makes,
        and the reasons for them, are set out in `docs/migrating-v2-to-v3.md`.

        Three conventions hold throughout, and knowing them removes most of the
        surprises:

        - **Numbers are numbers.** v2 returned every figure as a string; v3 uses
          the JSON number type.
        - **One representation per value.** v2 shipped each angle twice, once as a
          number and once pre-formatted for display. v3 returns the number, and
          the formatted form only when `include=formatted` asks for it.
        - **Units are declared, not implied.** Every response carries a
          `meta.units` block. Right ascension is in hours, following astronomical
          convention; every other angle is in degrees.

        Times are ISO 8601. Instants sent to the API may carry any offset and are
        interpreted as the instant they name. Instants returned are UTC unless a
        `timezone` is given, in which case they carry that zone's offset.
    contact:
        name: AstronomyAPI
        url: https://astronomyapi.com
    license:
        name: Proprietary
        url: https://astronomyapi.com/terms

servers:
    - url: https://api.astronomyapi.com/api/v3
      description: Production

security:
    - applicationKey: []

tags:
    - name: Bodies
      description: Where the Sun, the Moon and the planets are, and what they look like.
    - name: Search
      description: The catalogue of deep sky objects and stars.
    - name: Studio
      description: Rendered images of the sky.

paths:
    /positions:
        get:
            tags: [Bodies]
            summary: Positions of one or more bodies over a span of time
            operationId: getPositions
            description: |
                Returns where each requested body appears from the observer's
                location, sampled from `from` to `to` at intervals of `step`.

                Sampling is the main thing v3 adds. v2 could only return one
                position per day at a fixed time of day; `step` accepts any ISO
                8601 duration, so an altitude curve is one request rather than
                twenty-four.
            parameters:
                - $ref: '#/components/parameters/Bodies'
                - $ref: '#/components/parameters/Latitude'
                - $ref: '#/components/parameters/Longitude'
                - $ref: '#/components/parameters/Elevation'
                - $ref: '#/components/parameters/From'
                - $ref: '#/components/parameters/To'
                - $ref: '#/components/parameters/Step'
                - $ref: '#/components/parameters/Timezone'
                - $ref: '#/components/parameters/Origin'
                - $ref: '#/components/parameters/Refraction'
                - $ref: '#/components/parameters/Include'
                - $ref: '#/components/parameters/Limit'
                - $ref: '#/components/parameters/Cursor'
            responses:
                '200':
                    description: Positions for each requested body.
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/PositionsResponse'
                            examples:
                                singleBody:
                                    summary: Mars from London, one instant
                                    value:
                                        meta:
                                            observer:
                                                latitude: 51.4779
                                                longitude: -0.0015
                                                elevation: 0
                                            timezone: Europe/London
                                            units:
                                                rightAscension: hours
                                                declination: degrees
                                                altitude: degrees
                                                azimuth: degrees
                                                distance: au
                                            frames:
                                                equatorial: J2000
                                                horizontal: apparent, refracted
                                            sampling:
                                                from: '2024-06-21T11:00:00Z'
                                                to: '2024-06-21T11:00:00Z'
                                                step: PT1H
                                                count: 1
                                        data:
                                            - body:
                                                  id: mars
                                                  name: Mars
                                              samples:
                                                  - time: '2024-06-21T11:00:00Z'
                                                    rightAscension: 2.44012
                                                    declination: 13.41983
                                                    altitude: 41.26454
                                                    azimuth: 232.99871
                                                    distance:
                                                        au: 1.7782248
                                                        km: 266018470.2
                                                    constellation:
                                                        abbreviation: Ari
                                                        name: Aries
                                                    elongation: 51.52915
                                                    magnitude: 1.00953
                '400':
                    $ref: '#/components/responses/BadRequest'
                '401':
                    $ref: '#/components/responses/Unauthorized'
                '422':
                    $ref: '#/components/responses/UnprocessableEntity'

    /events:
        get:
            tags: [Bodies]
            summary: Eclipses and apsides for the observer's location
            operationId: getEvents
            description: |
                Returns the events falling between `from` and `to`, as seen from the
                observer's location.

                **Eclipses** are reported for the Sun and the Moon, with the
                altitude of the body at each contact so that it is clear how much of
                the event happens above the horizon. A solar eclipse is reported as
                this observer sees it, so the same eclipse is total from one place
                and partial from another.

                **Apsides** are reported for every body: the moments its distance
                from the Earth stops changing direction. They alternate between
                perigee and apogee. For a planet the perigee is when it appears
                largest and brightest, falling within days of opposition.

                v2 offered only eclipses, and only for the Sun and the Moon.
            parameters:
                - $ref: '#/components/parameters/EventBodies'
                - $ref: '#/components/parameters/EventTypes'
                - $ref: '#/components/parameters/Latitude'
                - $ref: '#/components/parameters/Longitude'
                - $ref: '#/components/parameters/Elevation'
                - $ref: '#/components/parameters/From'
                - $ref: '#/components/parameters/To'
                - $ref: '#/components/parameters/Timezone'
            responses:
                '200':
                    description: Events for each requested body.
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/EventsResponse'
                '400':
                    $ref: '#/components/responses/BadRequest'
                '401':
                    $ref: '#/components/responses/Unauthorized'
                '422':
                    $ref: '#/components/responses/UnprocessableEntity'

    /search:
        get:
            tags: [Search]
            summary: Find deep sky objects and stars
            operationId: search
            description: |
                Searches the catalogue either by name or by position. Give `term` to
                search by name, or `rightAscension` and `declination` together to
                search by position. The two are mutually exclusive.
            parameters:
                - $ref: '#/components/parameters/Term'
                - $ref: '#/components/parameters/MatchType'
                - $ref: '#/components/parameters/OrderBy'
                - $ref: '#/components/parameters/SearchRightAscension'
                - $ref: '#/components/parameters/SearchDeclination'
                - $ref: '#/components/parameters/SearchLimit'
                - $ref: '#/components/parameters/Offset'
            responses:
                '200':
                    description: Matching objects.
                    content:
                        application/json:
                            schema:
                                $ref: '#/components/schemas/SearchResponse'
                '400':
                    $ref: '#/components/responses/BadRequest'
                '401':
                    $ref: '#/components/responses/Unauthorized'
                '422':
                    $ref: '#/components/responses/UnprocessableEntity'

    /studio/star-chart:
        post:
            tags: [Studio]
            summary: Render a star chart
            operationId: createStarChart
            description: |
                Renders a chart of the sky as seen from the observer's location at a
                given instant, and returns a URL to the image.

                The chart can be framed either on a point in the sky, with a zoom
                level, or on a named constellation.
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/StarChartRequest'
            responses:
                '200':
                    $ref: '#/components/responses/Image'
                '400':
                    $ref: '#/components/responses/BadRequest'
                '401':
                    $ref: '#/components/responses/Unauthorized'
                '422':
                    $ref: '#/components/responses/UnprocessableEntity'

    /studio/moon-phase:
        post:
            tags: [Studio]
            summary: Render the Moon's phase
            operationId: createMoonPhase
            description: |
                Renders the Moon as it appears from the observer's location at a
                given instant, and returns a URL to the image.
            requestBody:
                required: true
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/MoonPhaseRequest'
            responses:
                '200':
                    $ref: '#/components/responses/Image'
                '400':
                    $ref: '#/components/responses/BadRequest'
                '401':
                    $ref: '#/components/responses/Unauthorized'
                '422':
                    $ref: '#/components/responses/UnprocessableEntity'


components:
    securitySchemes:
        applicationKey:
            type: http
            scheme: bearer
            description: |
                The application key, sent as `Authorization: Bearer <key>`. Keys are
                never accepted in the query string, where they would be recorded in
                logs and browser history.

    parameters:
        Bodies:
            name: bodies
            in: query
            required: false
            style: form
            explode: false
            description: |
                Which bodies to report, as a comma-separated list of ids. Omit to
                get all of them.

                The list is fixed and is given here in full, so there is nothing to
                look up at runtime. v2 had a `/bodies` endpoint that returned it;
                v3 does not, because a request to learn ten constants that never
                change is a round trip for nothing.

                `earth` is absent deliberately. Seen from the Earth it is at zero
                distance and has no direction, so the numbers v2 returned for it
                were whatever fell out of the arithmetic.
            schema:
                type: array
                items:
                    $ref: '#/components/schemas/BodyId'
            examples:
                one:
                    summary: A single body
                    value: [moon]
                several:
                    summary: Several bodies
                    value: [mars, venus]
        Latitude:
            name: latitude
            in: query
            required: true
            description: Latitude of the observer, in degrees, positive north.
            schema:
                type: number
                minimum: -90
                maximum: 90
                examples: [51.4779]
        Longitude:
            name: longitude
            in: query
            required: true
            description: Longitude of the observer, in degrees, positive east.
            schema:
                type: number
                minimum: -180
                maximum: 180
                examples: [-0.0015]
        Elevation:
            name: elevation
            in: query
            required: false
            description: |
                Height of the observer above sea level, in metres. Defaults to sea
                level. The upper bound covers the highest permanent observatories.
            schema:
                type: number
                default: 0
                minimum: -500
                maximum: 9000
        From:
            name: from
            in: query
            required: true
            description: |
                First instant to sample, as an ISO 8601 date or date-time. A bare
                date means midnight UTC on that date.
            schema:
                type: string
                examples: ['2024-06-21T00:00:00Z', '2024-06-21']
        To:
            name: to
            in: query
            required: true
            description: Last instant to sample. Must not precede `from`.
            schema:
                type: string
                examples: ['2024-06-22T00:00:00Z']
        Step:
            name: step
            in: query
            required: false
            description: |
                Interval between samples, as an ISO 8601 duration. `P1D` reproduces
                v2's one-sample-per-day behaviour, which is the default.
            schema:
                type: string
                default: P1D
                pattern: '^P(?!$)(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+S)?)?$'
                examples: [PT1H, PT15M, P1D]
        Timezone:
            name: timezone
            in: query
            required: false
            description: |
                IANA zone the returned instants are expressed in. `auto` derives it
                from the observer's coordinates, which is what v2 always did and
                remains the default. `UTC` is the unambiguous choice.
            schema:
                type: string
                default: auto
                examples: [auto, UTC, Europe/London]
        Origin:
            name: origin
            in: query
            required: false
            description: |
                Whether to measure from the observer's own position or from the
                centre of the Earth. The difference is parallax, worth up to about
                a degree for the Moon and arcseconds for the planets.
            schema:
                type: string
                default: topocentric
                enum: [topocentric, geocentric]
        Refraction:
            name: refraction
            in: query
            required: false
            description: |
                Whether the altitude accounts for the atmosphere bending light near
                the horizon. `none` gives the geometric altitude.
            schema:
                type: string
                default: standard
                enum: [standard, none]
        Include:
            name: include
            in: query
            required: false
            description: |
                Optional extras, comma separated. `formatted` adds a parallel block
                of sexagesimal strings for each angle, which v2 always sent whether
                or not the caller wanted them.
            schema:
                type: string
                examples: [formatted]
        Limit:
            name: limit
            in: query
            required: false
            description: Most samples to return per body before paginating.
            schema:
                type: integer
                default: 1000
                minimum: 1
                maximum: 10000
        Cursor:
            name: cursor
            in: query
            required: false
            description: Opaque cursor from `meta.sampling.nextCursor`.
            schema:
                type: string

        EventBodies:
            name: bodies
            in: query
            required: false
            style: form
            explode: false
            description: |
                Which bodies to report events for. Omit for all of them.

                v2 accepted only the Sun and the Moon here, because eclipses were
                the only events it knew about. Every body has apsides, so v3
                accepts the full list.
            schema:
                type: array
                items:
                    $ref: '#/components/schemas/BodyId'

        EventTypes:
            name: types
            in: query
            required: false
            style: form
            explode: false
            description: |
                Which kinds of event to report. Omit for all that apply to the
                bodies asked for.
            schema:
                type: array
                items:
                    type: string
                    enum: [lunar_eclipse, solar_eclipse, apsis]
        Term:
            name: term
            in: query
            required: false
            description: Name or catalogue designation to search for.
            schema:
                type: string
                minLength: 1
                examples: [andromeda, M31]
        MatchType:
            name: matchType
            in: query
            required: false
            description: |
                How `term` is matched. v2 spelled this `match_type`.
            schema:
                type: string
                enum: [exact, fuzzy]
                default: fuzzy
        OrderBy:
            name: orderBy
            in: query
            required: false
            description: |
                Field to sort by. v2 spelled this `order_by`.
            schema:
                type: string
                enum: [name]
        SearchRightAscension:
            name: rightAscension
            in: query
            required: false
            description: |
                Right ascension to search near, in hours. Must be given with
                `declination`. v2 called this `ra` and took it as a string.
            schema:
                type: number
                minimum: 0
                maximum: 24
        SearchDeclination:
            name: declination
            in: query
            required: false
            description: |
                Declination to search near, in degrees. Must be given with
                `rightAscension`. v2 called this `dec` and took it as a string.
            schema:
                type: number
                minimum: -90
                maximum: 90
        SearchLimit:
            name: limit
            in: query
            required: false
            description: |
                Most results to return. v2 declared this as a string because query
                parameters arrive as text; v3 declares the type it means.
            schema:
                type: integer
                default: 20
                minimum: 1
                maximum: 100
        Offset:
            name: offset
            in: query
            required: false
            description: Results to skip. Declared as an integer, not a string.
            schema:
                type: integer
                default: 0
                minimum: 0

    schemas:
        PositionsResponse:
            type: object
            required: [meta, data]
            properties:
                meta:
                    $ref: '#/components/schemas/Meta'
                data:
                    type: array
                    description: One entry per requested body, in the order asked for.
                    items:
                        $ref: '#/components/schemas/BodySamples'

        Meta:
            type: object
            required: [observer, timezone, units, frames, sampling]
            properties:
                observer:
                    $ref: '#/components/schemas/Observer'
                timezone:
                    type: string
                    description: IANA zone the instants below are expressed in.
                    examples: [Europe/London]
                units:
                    type: object
                    description: |
                        The unit each quantity is in. Present so that no caller has
                        to infer that right ascension is the one field not in
                        degrees.
                    additionalProperties:
                        type: string
                    examples:
                        - rightAscension: hours
                          declination: degrees
                          altitude: degrees
                          azimuth: degrees
                          distance: au
                frames:
                    type: object
                    description: |
                        The reference frame each set of coordinates is referred to.
                        Equatorial coordinates are J2000 unless stated otherwise;
                        horizontal coordinates are apparent, meaning corrected for
                        light travel time, the observer's motion, and refraction
                        unless it was turned off.
                    additionalProperties:
                        type: string
                sampling:
                    $ref: '#/components/schemas/Sampling'

        Observer:
            type: object
            required: [latitude, longitude, elevation]
            properties:
                latitude:
                    type: number
                    description: Degrees, positive north.
                longitude:
                    type: number
                    description: Degrees, positive east.
                elevation:
                    type: number
                    description: Metres above sea level.

        Sampling:
            type: object
            required: [from, to, step, count]
            properties:
                from:
                    type: string
                    format: date-time
                to:
                    type: string
                    format: date-time
                step:
                    type: string
                    description: ISO 8601 duration between samples.
                count:
                    type: integer
                    description: Samples returned per body.
                nextCursor:
                    type: string
                    description: |
                        Present only when the span was truncated by `limit`. Pass it
                        back as `cursor` to continue.

        BodySamples:
            type: object
            required: [body, samples]
            properties:
                body:
                    $ref: '#/components/schemas/BodyIdentity'
                samples:
                    type: array
                    items:
                        $ref: '#/components/schemas/Sample'

        BodyId:
            type: string
            description: |
                Stable lowercase identifier for a body. This is the complete set.
            enum:
                - sun
                - moon
                - mercury
                - venus
                - mars
                - jupiter
                - saturn
                - uranus
                - neptune
                - pluto

        BodyIdentity:
            type: object
            required: [id, name]
            properties:
                id:
                    $ref: '#/components/schemas/BodyId'
                name:
                    type: string
                    description: Display name.
                    examples: [Mars]

        Sample:
            type: object
            required:
                - time
                - rightAscension
                - declination
                - altitude
                - azimuth
                - distance
                - constellation
            properties:
                time:
                    type: string
                    format: date-time
                rightAscension:
                    type: number
                    description: Hours, in [0, 24).
                declination:
                    type: number
                    description: Degrees, in [-90, 90].
                altitude:
                    type: number
                    description: |
                        Degrees above the horizon. Negative when the body is below
                        it, which is a legitimate answer rather than an error.
                azimuth:
                    type: number
                    description: Degrees clockwise from true north, in [0, 360).
                distance:
                    $ref: '#/components/schemas/Distance'
                constellation:
                    $ref: '#/components/schemas/Constellation'
                elongation:
                    type: number
                    description: |
                        Degrees between the body and the Sun as seen from the
                        observer. Absent for the Sun.
                magnitude:
                    type: number
                    description: Apparent visual magnitude. Smaller is brighter.
                phase:
                    $ref: '#/components/schemas/Phase'
                formatted:
                    $ref: '#/components/schemas/Formatted'

        Distance:
            type: object
            required: [au, km]
            properties:
                au:
                    type: number
                    description: Astronomical units from the observer.
                km:
                    type: number
                    description: |
                        The same distance in kilometres. Returned so that callers do
                        not each hard-code their own value for the astronomical
                        unit and disagree with each other.

        Constellation:
            type: object
            required: [abbreviation, name]
            properties:
                abbreviation:
                    type: string
                    description: |
                        The IAU three-letter abbreviation, correctly capitalised.
                        This is the stable identifier; v2 also returned a lowercase
                        copy of it, which v3 drops.
                    examples: [Ari, CVn]
                name:
                    type: string
                    examples: [Aries]

        Phase:
            type: object
            description: Returned for the Moon only.
            required: [angle, fraction, name]
            properties:
                angle:
                    type: number
                    description: |
                        Degrees by which the Moon leads the Sun in ecliptic
                        longitude: 0 at new, 90 at first quarter, 180 at full.

                        v2 spelled this field `angel`.
                fraction:
                    type: number
                    minimum: 0
                    maximum: 1
                    description: |
                        Fraction of the Moon's disc that is lit, from 0 at new to 1
                        at full.

                        v2's figure for this was wrong twice over: it was scaled to
                        a range of 0 to 0.067, and it ran backwards, reporting its
                        largest value at new moon.
                name:
                    type: string
                    enum:
                        - New Moon
                        - Waxing Crescent
                        - First Quarter
                        - Waxing Gibbous
                        - Full Moon
                        - Waning Gibbous
                        - Last Quarter
                        - Waning Crescent

        Formatted:
            type: object
            description: |
                Sexagesimal renderings of the angles above, present only when
                `include=formatted` is given.
            properties:
                rightAscension:
                    type: string
                    examples: ['02h 26m 24s']
                declination:
                    type: string
                    examples: ["13° 25' 12\""]
                altitude:
                    type: string
                    examples: ["41° 15' 36\""]
                azimuth:
                    type: string
                    examples: ["233° 0' 0\""]

        Problem:
            type: object
            description: |
                An error, as RFC 9457 problem details. v2 returned the raw output of
                its schema validator, which exposed internal paths such as
                `instance.latitude` and had no stable machine-readable code.
            required: [type, title, status]
            properties:
                type:
                    type: string
                    format: uri
                    description: Stable identifier for the kind of problem.
                    examples: ['https://astronomyapi.com/problems/invalid-parameter']
                title:
                    type: string
                    examples: [Invalid parameter]
                status:
                    type: integer
                    examples: [422]
                detail:
                    type: string
                    examples: ['latitude must be between -90 and 90 degrees.']
                errors:
                    type: array
                    description: One entry per parameter at fault.
                    items:
                        type: object
                        required: [parameter, code, detail]
                        properties:
                            parameter:
                                type: string
                                examples: [latitude]
                            code:
                                type: string
                                examples: [out_of_range]
                            detail:
                                type: string

        EventsResponse:
            type: object
            required: [meta, data]
            properties:
                meta:
                    type: object
                    required: [observer, timezone, window]
                    properties:
                        observer:
                            $ref: '#/components/schemas/Observer'
                        timezone: { type: string }
                        window:
                            type: object
                            required: [from, to]
                            properties:
                                from: { type: string, format: date-time }
                                to: { type: string, format: date-tim

# --- truncated at 32 KB (45 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/astronomy-api/refs/heads/main/openapi/astronomy-api-v3-openapi.yaml