Search API
The Search API provides a unified interface for finding objects across the entire Craft catalog. It supports three search modes: semantic (natural language via pgvector embeddings), text (ILIKE pattern matching), and hybrid (both, with merged and boosted results).
Omnisearch
Section titled “Omnisearch”The primary search endpoint. Searches across satellites, celestial objects (stars, DSOs, comets), launches, and frequencies in a single query.
GET /api/searchQuery Parameters
Section titled “Query Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
q | string | — | Search query (min 1 character, required) |
types | string | — | Comma-separated type filter (e.g. satellite,star) |
limit | int | 20 | Max results (max 50) |
mode | string | hybrid | Search mode: hybrid, semantic, or text |
Type Shortcuts
Section titled “Type Shortcuts”Queries can include type prefixes to filter results without the types parameter:
| Prefix | Filters to |
|---|---|
/sat | satellite |
/star | star |
/dso | dso |
/launch | launch |
/freq | frequency |
/comet | comet |
For example, /sat ISS is equivalent to q=ISS&types=satellite.
Response
Section titled “Response”{ "query": "weather satellite", "results": [ { "name": "NOAA 20 (JPSS-1)", "target_type": "satellite", "target_id": "43013", "description": null, "magnitude": null, "score": 0.8234, "source": "semantic", "altitude_deg": 32.5, "countdown_seconds": null, "frequency_mhz": null, "groups": ["weather"], "url": "/catalog/satellite/43013" }, { "name": "GOES 16", "target_type": "satellite", "target_id": "41866", "description": null, "magnitude": null, "score": 0.7891, "source": "both", "altitude_deg": -15.2, "countdown_seconds": null, "frequency_mhz": null, "groups": ["weather", "geo"], "url": "/catalog/satellite/41866" } ], "count": 2, "mode": "hybrid"}Result Fields
Section titled “Result Fields”| Field | Type | Description |
|---|---|---|
name | string | Object name |
target_type | string | satellite, star, dso, comet, planet, launch, frequency |
target_id | string | Object identifier |
description | string|null | Short description |
magnitude | float|null | Visual magnitude (lower = brighter) |
score | float | Relevance score (0-1, higher is better) |
source | string | Match type: semantic, text, or both |
altitude_deg | float|null | Current altitude from observer (satellites only) |
countdown_seconds | float|null | Seconds until launch (launches only) |
frequency_mhz | float|null | Frequency in MHz (frequencies only) |
groups | list|null | Satellite groups (satellites only) |
url | string | Frontend catalog URL |
Search Modes
Section titled “Search Modes”| Mode | Behavior |
|---|---|
hybrid | Runs both semantic and text search, merges results, boosts dual matches |
semantic | Vector cosine similarity only. Falls back to text if embeddings fail |
text | ILIKE pattern matching only. No embedding service required |
How Scoring Works
Section titled “How Scoring Works”- Semantic results: Score is
1 - cosine_distance(closer to 1 = more relevant) - Text results: Fixed score of
0.5 - Dual matches: When an object appears in both semantic and text results, its score is boosted by
0.1and the source is marked asboth
Results are sorted by score descending and deduplicated by (target_type, target_id).
Live Enrichment
Section titled “Live Enrichment”Satellite results are enriched with live altitude data from the Skyfield engine. The altitude_deg field shows whether the satellite is currently above (> 0) or below (< 0) the observer’s horizon.
Examples
Section titled “Examples”# Natural language searchcurl "https://space.warehack.ing/api/search?q=amateur+radio+satellites"
# Type-filtered searchcurl "https://space.warehack.ing/api/search?q=ISS&types=satellite"
# Using type shortcutcurl "https://space.warehack.ing/api/search?q=/sat+ISS"
# Text-only mode (no embedding service needed)curl "https://space.warehack.ing/api/search?q=starlink&mode=text&limit=10"
# Search for launchescurl "https://space.warehack.ing/api/search?q=falcon+9&types=launch"const params = new URLSearchParams({ q: "amateur radio", mode: "hybrid", limit: "10",});
const resp = await fetch(`/api/search?${params}`);const data = await resp.json();
console.log(`Found ${data.count} results (mode: ${data.mode})`);data.results.forEach((r) => { console.log(`[${r.source}] ${r.name} (${r.target_type}) - score: ${r.score}`);});Semantic Search (Targets)
Section titled “Semantic Search (Targets)”A dedicated semantic-only search endpoint on the targets router. Searches celestial objects, satellites, and frequencies using vector similarity.
GET /api/targets/semantic-searchQuery Parameters
Section titled “Query Parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
q | string | — | Search query (min 2 characters) |
limit | int | 10 | Max results (max 50) |
Response
Section titled “Response”{ "query": "bright nebula visible tonight", "results": [ { "name": "M42 - Orion Nebula", "target_type": "dso", "target_id": "156", "description": "Diffuse nebula in Orion", "magnitude": 4.0, "distance": 0.1823 } ], "count": 1}The distance field is the raw cosine distance (lower = more similar). This is the inverse of the score field in omnisearch.
| Status | Description |
|---|---|
502 | Embedding service unavailable |
503 | Embedding service not configured |