openapi: 3.2.0
info:
title: CycleCalcs Astronomy Attribution API
version: 2.0.0
description: 'A read-only astronomy API that returns the named answer and the numbers behind it, with the frame, epoch, time scale and refraction model stated on every response. It reports angles, times and names, and attaches no meaning to any of them. Computed in real time with the MIT-licensed Astronomy Engine. This document is generated from the shipped route table (netlify/lib/v2/registry.mjs) by tools/generate-openapi.mjs, so it cannot list a route, a parameter or a requirement the API does not actually enforce. Computed astronomical output is unrestricted: use, store, redistribute and sell it without attribution. The one exception is GeoNames place data served by GET /v2/places and by any response that resolved a `place` parameter, which requires the credit line in meta.attribution; see GET /v2/attribution for the full source register.'
license:
name: Computed output unrestricted; third-party data credited per response
url: https://www.cyclecalcs.com/api/terms.html
termsOfService: https://www.cyclecalcs.com/api/terms.html
contact:
name: CycleCalcs
email: info@cyclecalcs.com
url: https://www.cyclecalcs.com/api.html
servers:
- url: https://www.cyclecalcs.com
security:
- {}
- RapidAPIKey: []
tags:
- name: Attribution
paths:
/v2/attribution:
get:
operationId: getAttribution
summary: Every source behind every endpoint, with its licence and what it obliges a caller to do
description: 'Every source behind every endpoint, with its licence and what it obliges a caller to do. Formats: json. Example: GET /v2/attribution?endpoint=/v2/moon'
parameters:
- $ref: '#/components/parameters/EndpointParam'
- $ref: '#/components/parameters/FieldsParam'
- $ref: '#/components/parameters/FormatParam'
- $ref: '#/components/parameters/PrecisionParam'
- $ref: '#/components/parameters/PrettyParam'
- $ref: '#/components/parameters/VerbosityParam'
responses:
'200':
description: The answer.
headers:
ETag:
description: Present when the cache class is deterministic or time-quantised. Send back as If-None-Match to get 304.
schema:
type: string
Cache-Control:
description: Browser caching directive for this response's cache class.
schema:
type: string
RateLimit:
description: draft-ietf-httpapi-ratelimit-headers usage for the current window.
schema:
type: string
content:
application/json:
schema:
$ref: '#/components/schemas/Envelope'
examples:
live:
summary: GET /v2/attribution?endpoint=/v2/moon
description: A real request to the running API, not a hand-written mock. It needs no key and can be opened directly, so the example is whatever the endpoint actually returns today.
externalValue: https://www.cyclecalcs.com/v2/attribution?endpoint=/v2/moon
'304':
description: Not Modified. Returned when If-None-Match matches the current ETag. No body.
'400':
description: 'The request could not be understood: a malformed or out-of-range parameter, an incomplete range, a conflicting pair of parameters, or a request too large for the compute budget.'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'404':
description: 'Not found: a `place`/`id`/target that does not resolve to anything, or a path this API does not serve.'
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'405':
description: Method not allowed. This API serves GET, HEAD and OPTIONS only.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'413':
description: The serialised response exceeded the hard size cap. Narrow the request with `fields`, verbosity=compact or a smaller range.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
'429':
description: Rate limited. Wait the number of seconds in Retry-After, or cache the response.
content:
application/problem+json:
schema:
$ref: '#/components/schemas/Problem'
tags:
- Attribution
components:
schemas:
Envelope:
type: object
description: The nine-key v2 response envelope. Every /v2 endpoint returns exactly these keys, in this order, on every 200 (spec-00 1.1).
required:
- endpoint
- computed_at
- query
- data
- warnings
- links
- meta
- attribution
- docs
properties:
endpoint:
type: string
description: The endpoint path that produced this response.
example: /v2/sun
computed_at:
type: string
format: date-time
description: 'A revision stamp, never a wall clock: identical requests return identical bytes, so a fixed_instant or reference response can be cached for a year and 304 stays reachable.'
example: '2026-08-01T00:00:00.000Z'
query:
type: object
description: 'The request as understood: every resolved input (instant, location, presentation options) plus `ignored`, in the order spec-00 13.2 defines. Shape is endpoint-specific.'
additionalProperties: true
data:
description: The answer. Shape is endpoint-specific; see each operation's summary and /api/reference.html.
warnings:
type: array
description: Machine-readable notices about this response. Empty when none apply; never changes the HTTP status.
items:
$ref: '#/components/schemas/Warning'
links:
type: object
description: Related URLs. self reproduces this exact response; docs is always present; others (page, spec, next, first, explain) appear where relevant.
additionalProperties:
type: string
format: uri
example:
self: https://www.cyclecalcs.com/v2/sun?at=2026-06-21&lat=51.4778&lon=-0.0015
docs: https://www.cyclecalcs.com/api/reference.html#sun
spec: https://www.cyclecalcs.com/v2/openapi.json
page: https://www.cyclecalcs.com/sunrise-sunset-calculator.html
explain: https://www.cyclecalcs.com/learn/seasons.html
meta:
type: object
description: 'Provenance: engine version, rights and attribution, cache class, accuracy statement, tzdb version, and endpoint-specific conventions (refraction model, horizon definitions, time scales, and so on). Never subject to `fields` projection.'
additionalProperties: true
attribution:
type: string
description: The credit line, byte-identical to meta.attribution.text.
example: Computed by CycleCalcs (cyclecalcs.com) with the MIT-licensed Astronomy Engine. Positional astronomy only.
docs:
type: string
format: uri
description: The human-readable reference section for this endpoint.
example: https://www.cyclecalcs.com/api/reference.html#sun
Problem:
type: object
description: An RFC 9457 problem detail document. Served on every non-2xx v2 response with Content-Type application/problem+json.
required:
- type
- title
- status
- detail
- code
- parameter
- hint
- example
- supported
- request_id
- error_chain
- docs
properties:
type:
type: string
format: uri
description: 'A URI identifying the error type, ending in a #fragment matching `code` in kebab-case. Dereferenceable at /api/errors.html.'
example: https://www.cyclecalcs.com/api/errors.html#bad-latitude
title:
type: string
description: A short, fixed, human-readable summary of the error type (not the instance).
example: Latitude is not a number from -90 to 90
status:
type: integer
enum:
- 400
- 401
- 404
- 405
- 406
- 409
- 410
- 413
- 414
- 422
- 429
- 500
- 503
description: The HTTP status code, repeated from the response line.
example: 400
detail:
type: string
description: A human-readable explanation specific to this occurrence.
example: lat must be a number from -90 to 90; got "999".
instance:
type: string
format: uri
description: 'Present only on non-cacheable statuses (429, 503, and unexpected 500s): `type` with ?request_id=<id> inserted before its #fragment.'
example: https://www.cyclecalcs.com/api/errors.html?request_id=ba0c53d302f09df4#rate-limited
code:
type: string
enum:
- AMBIGUOUS_LOCAL_TIME
- AMBIGUOUS_LONGITUDE_FORMAT
- AMBIGUOUS_PLACE
- BAD_ALARM
- BAD_APERTURE
- BAD_BOOLEAN
- BAD_BORTLE
- BAD_CALENDAR_SOURCE
- BAD_CLIENT
- BAD_COUNT
- BAD_CURSOR
- BAD_CYCLE_KEY
- BAD_DATE
- BAD_DEPRESSION
- BAD_ECLIPSE_DIRECTION
- BAD_ECLIPSE_TYPE
- BAD_ELEVATION
- BAD_FIELDS
- BAD_FORMAT
- BAD_HEIGHT_OF_EYE
- BAD_HEMISPHERE
- BAD_INCLUDE
- BAD_INDEX_ERROR
- BAD_LATITUDE
- BAD_LIMIT
- BAD_LIMITING_MAGNITUDE
- BAD_LONGITUDE
- BAD_MOON_ALTITUDE
- BAD_MOTION
- BAD_NELM
- BAD_NODE_MODEL
- BAD_PAIR
- BAD_PAIRS
- BAD_PARAMETER_VALUE
- BAD_PHASE_SELECTOR
- BAD_PLACE
- BAD_RADEC
- BAD_RANGE
- BAD_RANGE_VALUE
- BAD_REFRACTION
- BAD_SEARCH_HORIZON
- BAD_SEXTANT_ALTITUDE
- BAD_SIZE
- BAD_STEP
- BAD_TIMEZONE
- BAD_TIME_FORMAT
- BODY_NOT_GEOCENTRIC
- BODY_NOT_SUPPORTED_HERE
- BODY_REQUIRED
- BODY_UNAVAILABLE
- BUDGET_EXCEEDED
- CLUSTER_PARAMETERS_REQUIRED
- COMPUTATION_FAILED
- COMPUTE_BUDGET_EXCEEDED
- CONFLICTING_AYANAMSA_INPUTS
- CONFLICTING_PARAMETERS
- CONFLICTING_TIME_INPUTS
- DATASET_UNAVAILABLE
- DATE_OUT_OF_RANGE
- ENDPOINT_BLOCKED
- ENDPOINT_RETIRED
- ENDPOINT_WITHDRAWN
- EXPIRED_KEY
- FIELD_NOT_COMPUTED
- HOUSE_SYSTEM_UNDEFINED
- INCOMPLETE_LOCATION
- INCOMPLETE_RANGE
- INTERNAL_ERROR
- INVALID_CHARACTER
- INVALID_KEY
- INVALID_LOT_EXPRESSION
- INVALID_ORB_TABLE
- LATITUDE_AT_POLE
- LATITUDE_TOO_EXTREME
- LOCATION_REQUIRED
- LONGITUDE_REQUIRED
- METHOD_NOT_ALLOWED
- NONEXISTENT_LOCAL_TIME
- NOT_ACCEPTABLE
- OBJECT_NOT_FOUND
- OUTSIDE_MODEL_RANGE
- PARAMETER_TOO_LONG
- PERFECTION_BUDGET_EXCEEDED
- PERFECTION_WINDOW_TOO_LARGE
- PERFECTION_WINDOW_UNSUPPORTED_COMBINATION
- PLACE_INDEX_UNAVAILABLE
- PLACE_NOT_FOUND
- QUERY_TOO_SHORT
- RANGE_TOO_LARGE
- RATE_LIMITED
- RESPONSE_TOO_LARGE
- REVOKED_KEY
- SERVICE_UNAVAILABLE
- SKY_CLASS_REQUIRED
- STAR_POOL_TIMEOUT
- STAR_SLOT_FAILED
- TIMEZONE_AUTO_UNSUPPORTED
- TIMEZONE_DATABASE_UNAVAILABLE
- TIMEZONE_REQUIRED
- TIME_REQUIRED
- TIME_REQUIRED_FOR_HOUSES
- TOO_MANY_BODIES
- TOO_MANY_CALENDAR_SOURCES
- TOO_MANY_DEPRESSIONS
- TOO_MANY_PAIRS
- TOO_MANY_PARAMETERS
- TOO_MANY_SHOWERS
- UNKNOWN_ASPECT
- UNKNOWN_AYANAMSA
- UNKNOWN_BODY
- UNKNOWN_DERIVED
- UNKNOWN_ENDPOINT
- UNKNOWN_HOUSE_SYSTEM
- UNKNOWN_LOT_TERM
- UNKNOWN_POINT
- UNKNOWN_SHOWER
- URI_TOO_LONG
description: The stable, SCREAMING_SNAKE_CASE error code a client should branch on. The full registry is at GET /v2/enums?set=error_codes.
example: BAD_LATITUDE
parameter:
type:
- string
- 'null'
description: The query parameter most responsible for this error, when there is one.
example: lat
hint:
type:
- string
- 'null'
description: A short suggestion for fixing the request.
example: Use a signed decimal, for example lat=51.5 for north and lat=-51.5 for south. Do not append N or S
example:
type:
- string
- 'null'
description: A worked example URL or value, when one is more useful than the hint alone.
supported:
type:
- array
- 'null'
items: {}
description: The accepted values for the offending parameter, when the error is about picking from a closed set.
request_id:
type:
- string
- 'null'
description: 16 lowercase hex characters, present only on non-cacheable statuses. Quote it when reporting a 500.
example: ba0c53d302f09df4
error_chain:
type:
- array
- 'null'
items: {}
description: For an error caused by resolving another parameter first (rare), the sequence of codes that led here.
docs:
type: string
format: uri
description: The API reference index.
example: https://www.cyclecalcs.com/api/reference.html
additionalProperties: true
Warning:
type: object
description: One machine-readable notice. Exactly four keys, in this order (spec-00 11.4). Never changes the HTTP status.
required:
- code
- message
- field
- value
properties:
code:
type: string
enum:
- ambiguous_local_time
- antipodal_pair_not_aspected
- approximates_undefined_placidus
- assumed_utc
- birth_time_unknown
- blocked_layer_omitted
- cusps_not_monotonic
- dataset_stale
- decorative_starfield
- dms_rounds_to_next_sign
- dst_discontinuity
- duplicate_alarm
- duplicate_aspect
- duplicate_body
- duplicate_depression
- duplicate_derived
- duplicate_house_system
- duplicate_include
- duplicate_pair
- duplicate_parameter
- duplicate_point
- duplicate_shower
- duplicate_source
- elevation_ignored
- estimate_only
- extrapolated_epoch
- field_blocked
- fields_ignored
- harmonic_orb_mode_has_no_effect
- high_latitude_caution
- horizon_overridden
- house_system_substituted
- large_intercept
- lot_term_null
- low_altitude_precision
- mean_node_model
- model_disagreement
- model_epoch_only
- moon_dominates
- no_astronomical_darkness
- no_location_orientation
- no_search_result
- nonexistent_local_time_shifted
- not_visible_from_location
- oblateness_simplified
- orbit_arc_truncated
- parameter_ignored
- perfection_search_truncated
- place_ambiguous
- place_index_tier_2
- place_matched_by_substring
- placement_within_error_of_boundary
- polar_angles_flipped
- polar_day
- polar_night
- polar_region
- prose_window_differs
- refraction_below_cutoff
- render_degenerate
- rounded_parameter
- sect_tests_disagree
- shape_ignored
- source_window_clipped
- station_near_window_edge
- station_search_truncated
- time_format_not_applicable
- time_scale_undefined
- timezone_from_place
- truncated_results
- tz_source_boundary_1970
- tzdb_lmt_interval
- unknown_parameter
- unusual_navigational_body
- vertex_undefined_at_equator
description: A stable, lower_snake_case token. The full registry is at GET /v2/enums?set=warning_codes.
message:
type: string
description: A human-readable explanation. Not parsed by machines; use `code`.
field:
type:
- string
- 'null'
description: The data or query pointer the warning is about, dot-addressed the same way `fields` is. Null when the warning is not about one field.
value:
description: The value involved, when there is a single obvious one to show. Null otherwise.
parameters:
EndpointParam:
name: endpoint
in: query
required: false
description: A v2 endpoint path (or its bare slug), to scope the response to that one endpoint.
schema:
type: string
enum:
- /v2
- /v2/conventions
- /v2/enums
- /v2/attribution
- /v2/positions
- /v2/rise-set
- /v2/sun
- /v2/moon
- /v2/time
- /v2/seasons
- /v2/apsides
- /v2/moon-nodes
- /v2/eclipses
- /v2/planet-board
- /v2/retrogrades
- /v2/conjunctions
- /v2/separation
- /v2/cycles
- /v2/twilight
- /v2/dark-window
- /v2/sidereal-time
- /v2/equation-of-time
- /v2/libration
- /v2/jupiter-moons
- /v2/sky-quality
- /v2/places
- /v2/phases
- /v2/planet-events
- /v2/today
example: /v2/moon
PrecisionParam:
name: precision
in: query
required: false
description: Decimal places for numeric fields.
schema:
type: integer
minimum: 0
maximum: 9
default: 6
example: 6
FormatParam:
name: format
in: query
required: false
description: Response representation. Each endpoint serves a subset of json, csv and txt; see that operation's description for the exact list, or GET /v2 for every endpoint's formats array. An unsupported value is 400 BAD_FORMAT with the accepted list in `supported`.
schema:
type: string
example: json
FieldsParam:
name: fields
in: query
required: false
description: Comma-separated dot paths into `data` (for example moon.phase_name,moon.illumination) so only those fields are returned. Up to 64 paths; an array element is addressed by its object key, never by index.
schema:
type: string
VerbosityParam:
name: verbosity
in: query
required: false
description: full includes prose notes, frame definitions and withheld-field reasons in meta. compact keeps every value and every machine-readable name and drops the prose.
schema:
type: string
enum:
- full
- compact
default: full
example: full
PrettyParam:
name: pretty
in: query
required: false
description: Whether the JSON body is indented (1) or compact (0). Has no effect on csv or txt.
schema:
type: integer
enum:
- 0
- 1
default: 1
example: 1
securitySchemes:
RapidAPIKey:
type: apiKey
in: header
name: X-RapidAPI-Key
description: 'Optional, and read only by the RapidAPI gateway host (cyclecalcs-astronomy-api3.p.rapidapi.com), never by the origin in `servers`. Calling this API directly needs no key and is served at the free anonymous tier: 300 requests a minute, 2,000 an hour and 5,000 a day, counted per caller rather than globally. A key raises those limits to the subscribed tier and is what monthly volume is metered against; it is sold at https://rapidapi.com/info-8KZIhinZ9/api/cyclecalcs-astronomy-api3. It is never accepted as a query parameter, on either host.'
externalDocs:
description: Human-readable endpoint reference
url: https://www.cyclecalcs.com/api/reference.html