Les passages de satellites, sous forme d'API
Un seul appel HTTP renvoie tous les passages d'un satellite au-dessus d'un point du globe : lever, culmination et coucher, la trajectoire échantillonnée toutes les 10 s, la vitesse radiale et le décalage Doppler, l'éclairement et la visibilité — et l'âge des éléments orbitaux utilisés, pour que vos utilisateurs sachent ce que valent les horaires.
Premier appel
L'ISS au-dessus de Lyon, les 48 prochaines heures, passages au-dessus de 10°curl -H "X-API-Key: $NEXTPASS_API_KEY" \
'https://sat-pass-predictor-api.onrender.com/v1/passes?noradId=25544&lat=45.7578&lon=4.832&alt=170'{
"satellite": { "noradId": 25544, "name": "ISS (ZARYA)" },
"tle": {
"epoch": "2026-09-30T06:12:44.123Z",
"ageSeconds": 21304,
"source": "CelesTrak",
"fetchedAt": "2026-09-30T09:40:02Z",
"line1": "1 25544U 98067A ...",
"line2": "2 25544 51.63 ..."
},
"observer": { "latitudeDeg": 45.7578, "longitudeDeg": 4.832, "altitudeM": 170 },
"minElevationDeg": 10,
"frequencyMhz": null,
"computedAt": "2026-09-30T12:07:48Z",
"passes": [
{
"aos": { "instant": "2026-09-30T19:42:10.412Z", "azimuthDeg": 247.1, "elevationDeg": 10.0, ... },
"culmination": { "instant": "2026-09-30T19:45:21.870Z", "azimuthDeg": 172.4, "elevationDeg": 48.6, ... },
"los": { "instant": "2026-09-30T19:48:33.095Z", "azimuthDeg": 97.9, "elevationDeg": 10.0, ... },
"durationSeconds": 382,
"track": [ { "instant": "...", "azimuthDeg": 247.1, "elevationDeg": 10.0, "rangeKm": 1362.4,
"rangeRateKmS": -6.41, "dopplerHz": null, "subPoint": { ... },
"illuminated": true, "visible": true }, ... ]
}
]
} Chaque instant est en UTC ISO-8601 : les fuseaux horaires relèvent de l'affichage et l'API refuse d'avoir un avis là-dessus. aos, culmination et los sont des points de track lui-même : un instant étiqueté se trouve toujours sur la courbe qui en est tracée. Une liste passes vide est un résultat, pas une erreur.
tle.ageSeconds est calculé une fois par le serveur, à partir de l'époque des éléments. Affichez-le : l'erreur de SGP4 croît avec lui, de l'ordre de quelques kilomètres par jour en orbite basse.
Points d'accès
https://sat-pass-predictor-api.onrender.com| Route | Renvoie | Accès |
|---|---|---|
| GET /v1/passes | Les passages d'un satellite au-dessus d'un site. | X-API-Key, une requête |
| GET /v1/passes/batch | Chaque satellite au-dessus de chaque site : jusqu'à 10 satellites, 10 sites, 25 prédictions. | X-API-Key, une requête par prédiction |
| GET /api/satellites?q= | Les satellites actifs dont le nom CelesTrak ou le numéro correspond, pour un champ de recherche. | Public |
Paramètres
/v1/passes| Nom | Format | Défaut | Signification |
|---|---|---|---|
| noradId | entier, 1–99999 | obligatoire | Numéro de catalogue NORAD du satellite. |
| lat | degrés, de −90 à 90 | obligatoire | Latitude de l'observateur (WGS84). |
| lon | degrés, de −180 à 180 | obligatoire | Longitude de l'observateur. |
| alt | mètres, de −500 à 9000 | 0 | Altitude au-dessus de l'ellipsoïde WGS84, pas au-dessus du niveau de la mer. |
| hours | entier, 1–240 | 48 | Durée de la fenêtre, à partir de la requête. |
| minElevation | degrés, 0–89 | 10 | Élévation qu'un passage doit dépasser pour compter ; l'AOS et le LOS se trouvent sur ce seuil. |
| frequencyMhz | MHz, 1–300000 | aucune | Porteuse descendante ; ajoute dopplerHz à chaque point et chaque phase. |
Le Doppler pour les radioamateurs
Vitesse radiale sur chaque point ; le décalage quand vous indiquez une fréquencecurl -H "X-API-Key: $NEXTPASS_API_KEY" \
'https://sat-pass-predictor-api.onrender.com/v1/passes?noradId=25544&lat=45.7578&lon=4.832&frequencyMhz=145.8' Chaque point et chaque phase portent rangeRateKmS, issu de la vitesse calculée par Orekit plutôt que de différences de distances — négatif pendant que le satellite se rapproche. Avec frequencyMhz, chacun porte aussi dopplerHz, le décalage au premier ordre à appliquer au récepteur, −f · rangeRate / c. Pour une liaison montante, appliquez le signe opposé. Demander plusieurs fréquences ne coûte qu'une propagation : le décalage est mis à l'échelle à partir de la prédiction en cache.
Prédictions groupées
Une flotte de satellites au-dessus d'un réseau de stations sol, en un seul appelcurl -H "X-API-Key: $NEXTPASS_API_KEY" \
'https://sat-pass-predictor-api.onrender.com/v1/passes/batch?noradId=25544,20580&site=45.7578,4.8320,170&site=-33.92,18.42&track=false'sitevautlat,lonoulat,lon,alt; répétez-le pour chaque site. Les doublons sont supprimés avant le décompte.resultsest ordonné par satellite. Chaque entrée contient soitprediction, exactement le corps de/v1/passes, soiterror, exactement son Problem Details. Un satellite en échec ne fait pas échouer le lot.- Un lot est admis en entier ou refusé en entier, et compte une requête par prédiction. Demandez
track=falsesi vous n'avez pas besoin des polylignes : 25 prédictions en cache reviennent en quelques millisecondes et pèsent un demi-mégaoctet au lieu de 13. - Il n'y a pas de
frequencyMhzdans un lot ; calculez vous-même−rangeRateKmS / 299792.458 × f.
Depuis votre code
Aucun SDK à installer : un GET et un en-têteconst url = new URL('https://sat-pass-predictor-api.onrender.com/v1/passes');
url.search = new URLSearchParams({ noradId: '25544', lat: '45.7578', lon: '4.832' }).toString();
const response = await fetch(url, { headers: { 'X-API-Key': process.env.NEXTPASS_API_KEY } });
if (!response.ok) {
const problem = await response.json(); // RFC 9457: branch on problem.type
throw new Error(`${problem.title}: ${problem.detail}`);
}
const { passes } = await response.json();
for (const pass of passes) console.log(pass.aos.instant, pass.culmination.elevationDeg);import os, requests
response = requests.get(
"https://sat-pass-predictor-api.onrender.com/v1/passes",
params={"noradId": 25544, "lat": 45.7578, "lon": 4.832},
headers={"X-API-Key": os.environ["NEXTPASS_API_KEY"]},
timeout=60,
)
if not response.ok:
problem = response.json() # RFC 9457: branch on problem["type"]
raise RuntimeError(f"{problem['title']}: {problem.get('detail')}")
for p in response.json()["passes"]:
print(p["aos"]["instant"], p["culmination"]["elevationDeg"])Gardez la clé sur un serveur. Une clé livrée dans une page web est une clé que n'importe qui peut lire et dépenser. Les appels de navigateur d'une autre origine sont refusés sauf si l'opérateur autorise votre origine, et même alors CORS n'est pas une authentification.
Erreurs
Problem Details RFC 9457, un seul format partout Basez-vous sur type, jamais sur la phrase : deux échecs différents partagent le statut 503. Chaque type vaut https://github.com/warlaxx/sat-pass-predictor/errors/ suivi de l'identifiant ci-dessous.
| État | Type | Que faire |
|---|---|---|
| 400 | invalid-request | Un paramètre est manquant, mal formé ou hors limites. Inutile de réessayer tel quel. |
| 400 | batch-exceeds-rate-limit | Un lot plus grand que la limite par minute de la clé : il ne pourrait jamais être admis. |
| 401 | invalid-api-key | X-API-Key absente, inconnue ou révoquée. |
| 404 | unknown-satellite | Le numéro est absent de CelesTrak : très probablement un objet rentré dans l'atmosphère. |
| 429 | rate-limit-exceeded · daily-quota-exceeded · monthly-quota-exceeded | Limite atteinte. Retry-After et resetsAt disent quand ; limit dit laquelle. |
| 503 | tle-unavailable | Aucune source d'éléments n'a répondu et aucun n'est conservé. Réessayez dans 15 s environ. |
| 503 | tle-stale | Les seuls éléments conservés ont plus de 7 jours : refusés plutôt qu'affichés. |
| 503 | api-access-unavailable | Le décompte des quotas est indisponible. L'API refuse par sécurité ; réessayez plus tard. |
Limites à connaître
Toutes les offres →- L'aperçu gratuit autorise 100 requêtes par jour UTC et 10 par minute, avec une clé.
- Les limites par minute sont des fenêtres fixes alignées sur la minute UTC, pas une fenêtre glissante. Une réponse en cache compte comme une réponse calculée : vous payez l'appel, pas le CPU.
- Toute requête admise compte, y compris celle qui échoue ensuite à la validation. Les clés invalides, les refus de quota et les requêtes préliminaires CORS ne comptent pas.
- Les réponses portent
Cache-Control: no-store. Ne les placez pas derrière un cache partagé. - Le service tourne actuellement sur une instance gratuite qui se met en veille : le premier appel après une période calme peut prendre jusqu'à une demi-minute. Utilisez un délai d'attente de 60 s. Consultez la page d'état.