API reference

The read-model REST API returns recent crossmatches for objects that had an alert in a time window, grouped by object, at a caller-selected detail level. Responses are JSON.

Endpoint

GET /api/recent-crossmatches

Results are keyset (cursor) paged, newest first. Follow the top-level next_cursor to page through the whole window; it is null when the window is exhausted.

Query parameters

All parameters are optional
Parameter Values Description
start ISO-8601 timestamp (UTC) Window start. Defaults to end minus 12 hours.
end ISO-8601 timestamp (UTC) Window end. Defaults to now.
time_field ingest_time (default), event_time Which alert timestamp the window filters on: arrival time or observation time.
detail ids, position, matches (default), full Cumulative detail level per object (see below).
page_size positive integer Objects per page, clamped down to the server maximum.
cursor opaque token A next_cursor from a prior page. It pins start, end, time_field, and detail; supplying any of those with a conflicting value is a 400.

Detail levels

Detail levels are cumulative, each adding to the one before it:

Response envelope

Every successful response wraps the objects with the resolved query metadata:

{
  "window": {"start": "...", "end": "..."},
  "time_field": "ingest_time",
  "detail": "matches",
  "page_size": 1000,
  "count": 2,
  "next_cursor": null,
  "objects": [ ... ]
}

count is the number of objects on this page (not a whole-set total). objects contains one entry per matched diaObjectId (objects with no match are omitted).

Example request

curl "https://example.org/api/recent-crossmatches?detail=matches&page_size=2"

Success (200)

{
  "window": {"start": "2026-08-10T00:00:00+00:00", "end": "2026-08-10T12:00:00+00:00"},
  "time_field": "ingest_time",
  "detail": "matches",
  "page_size": 2,
  "count": 1,
  "next_cursor": "eyJ0MCI6IC4uLn0=",
  "objects": [
    {
      "diaObjectId": 1234567890123456789,
      "ra": 150.113,
      "dec": 2.205,
      "matches": [
        {
          "catalog_name": "gaia_dr3",
          "catalog_source_id": "987654321098765432",
          "separation_arcsec": 0.42
        }
      ]
    }
  ]
}

Error — invalid parameter (400)

An unparseable timestamp, unknown detail/time_field, non-positive page_size, malformed or conflicting cursor, or an out-of-range window returns a 400 with a JSON error body:

{
  "error": "detail must be one of ('ids', 'position', 'matches', 'full'), got 'everything'"
}

Error — wrong method (405)

Only GET is supported. Any other method returns a 405:

{
  "error": "method not allowed"
}