CycleCalcs Places API

The Places API from CycleCalcs — 1 operation(s) for places.

OpenAPI Specification

cyclecalcs-places-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: CycleCalcs Astronomy Places 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: Places
paths:
  /v2/places:
    get:
      operationId: getPlaces
      summary: Place-name search and reverse lookup against the self-hosted GeoNames index, returning name, region, country, coordinates and IANA timezone with a stable place_id
      description: 'Place-name search and reverse lookup against the self-hosted GeoNames index, returning name, region, country, coordinates and IANA timezone with a stable place_id. Formats: json, csv. Every response is GeoNames data under CC BY 4.0, so every response carries rights: attribution_required and the credit in meta.attribution.text. The rest of the API is unrestricted. Example: GET /v2/places?q=cambridge&limit=5'
      parameters:
      - name: q
        in: query
        required: false
        description: A place name to search for, at least 2 characters after trimming. Mutually exclusive with `id` and with `lat`/`lon`.
        schema:
          type: string
          minLength: 2
          maxLength: 128
        example: cambridge
      - name: id
        in: query
        required: false
        description: An exact place_id from a previous /v2/places response, for example us-n35198-w111651. Mutually exclusive with `q` and with `lat`/`lon`.
        schema:
          type: string
          pattern: ^[A-Za-z]{2}-[NSns]\d{5}-[EWew]\d{6}$
        example: gb-n52125-w000008
      - $ref: '#/components/parameters/LatitudeParam'
      - $ref: '#/components/parameters/LongitudeParam'
      - name: country
        in: query
        required: false
        description: 'Restricts a name search to one country: an ISO 3166-1 alpha-2 code (case-insensitive) or a country name.'
        schema:
          type: string
        example: GB
      - name: region
        in: query
        required: false
        description: Restricts a name search to one admin region (state or province name) as stored in the index.
        schema:
          type: string
        example: Cambridgeshire
      - name: limit
        in: query
        required: false
        description: Maximum number of place matches to return, 1 to 25.
        schema:
          type: integer
          minimum: 1
          maximum: 25
          default: 6
        example: 5
      - name: min_population
        in: query
        required: false
        description: Only return places at or above this population. The index stores population to the nearest 1,000, so the value is rounded up to the next thousand.
        schema:
          type: integer
          minimum: 0
          maximum: 40000000
        example: 100000
      - name: radius_km
        in: query
        required: false
        description: Search radius in kilometres for a reverse (lat/lon) lookup. Default 250.
        schema:
          type: number
          minimum: 1
          maximum: 2000
        example: 25
      - $ref: '#/components/parameters/FormatParam'
      - $ref: '#/components/parameters/FieldsParam'
      - $ref: '#/components/parameters/ShapeParam'
      - $ref: '#/components/parameters/PrecisionParam'
      - $ref: '#/components/parameters/PrettyParam'
      - $ref: '#/components/parameters/VerbosityParam'
      - $ref: '#/components/parameters/TimeFormatParam'
      responses:
        '200':
          description: 'The answer. Every response is GeoNames data under CC BY 4.0, so every response carries rights: attribution_required and the credit in meta.attribution.text. The rest of the API is unrestricted.'
          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/places?q=cambridge&limit=5
                  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/places?q=cambridge&limit=5
            text/csv:
              schema:
                type: string
                description: A CSV rendering of the same answer. See meta and the CSV header comment for provenance.
              examples:
                live:
                  summary: GET /v2/places?q=cambridge&limit=5&format=csv
                  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/places?q=cambridge&limit=5&format=csv
        '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:
      - Places
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:
    LatitudeParam:
      name: lat
      in: query
      required: false
      description: Latitude in decimal degrees, north positive. No compass suffix (do not append N or S). Required together with lon, or neither.
      schema:
        type: number
        minimum: -90
        maximum: 90
      example: 51.4778
    PrecisionParam:
      name: precision
      in: query
      required: false
      description: Decimal places for numeric fields.
      schema:
        type: integer
        minimum: 0
        maximum: 9
        default: 6
      example: 6
    ShapeParam:
      name: shape
      in: query
      required: false
      description: nested returns the documented object tree. flat returns one object with dotted keys, format=json only.
      schema:
        type: string
        enum:
        - nested
        - flat
        default: nested
      example: nested
    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
    TimeFormatParam:
      name: time_format
      in: query
      required: false
      description: 'How instants are rendered: iso for ISO 8601 strings carrying the effective offset, or unix for integer seconds since the epoch.'
      schema:
        type: string
        enum:
        - iso
        - unix
        default: iso
      example: iso
    LongitudeParam:
      name: lon
      in: query
      required: false
      description: Longitude in decimal degrees, east positive. No compass suffix (do not append E or W). Required together with lat, or neither.
      schema:
        type: number
        minimum: -180
        maximum: 180
      example: -0.0015
    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