Aller au contenu

omnilab/launches

Omnilab Launches: orbital launches of The Space Devs' Launch Library 2, past and planned - a launch by id (rocket, provider, mission and orbit, pad and its place, date and its precision, window, status, probability, failure), a search by text, and the launches of a period as occurrences, each with its time and its pad's place, filtered by provider, rocket, location, crew, status or orbit; no key needed (15 calls an hour).

Étage
Fournisseur · Omnilab
Version
1.x
Suite de conformité
non branchée
Vérifié en réel
Son README ne le dit pas
Licence
MIT
composer require omnilab/launches:1.x-dev

The Space Devs' Launch Library 2 (https://ll.thespacedevs.com/2.3.0/) for omnisense/omnilab: orbital launches, past and planned, by id or text - rocket, provider, mission, orbit, pad, status - as entities, and the launches of a period as occurrences at their pads. No key (15 calls an hour).

Installation

composer require omnilab/launches
use Omnilab\Launches\LaunchesSourceFactory;

$launches = (new LaunchesSourceFactory($httpClient))->create([
    'mailto' => 'support@glitchr.io',  // optional, in the User-Agent
    'api_key' => null,                 // optional: a key from The Space Devs ("Authorization: Token ...")
    'base_uri' => 'https://lldev.thespacedevs.com/2.3.0/',   // to develop: stale data, no rate limit
]);

With the Symfony bundle, the factory is registered as launches when the bundle knows it; otherwise register LaunchesSourceFactory as a service (it is autoconfigured as a SourceFactoryInterface).

Credentials

None needed: Launch Library 2 answers 15 calls an hour without a key (a 429 beyond). A higher limit comes with a key The Space Devs give their supporters (on Patreon), given as api_key and sent as Authorization: Token .... To develop, The Space Devs ask that their development server be used: base_uri: https://lldev.thespacedevs.com/2.3.0/ (stale, limited data, no rate limit).

Options

The factory's options, with the defaults it applies (LaunchesSourceFactory):

Option Type Default Required Effect
api_key ?string null no a supporter's key from The Space Devs, sent as Authorization: Token ...; null: no header, 15 calls an hour
mailto ?string null no a contact address, sent in the User-Agent
user_agent ?string null no the whole User-Agent, in place of the one made from mailto
throttle float 0 no seconds left between two calls; the limit is counted an hour (15 without a key): the caller keeps to it
base_uri string https://ll.thespacedevs.com/2.3.0/ no LL2 2.3.0: the live server, or the development one (https://lldev.thespacedevs.com/2.3.0/)

Per call, occurrences() reads the filters provider, rocket, location, crewed, status and orbit (below); any other key, the shared ones (country, kind...) included, is refused before any call.

Capabilities

capabilities() answers entity, search, occurrences; an operation it does not answer throws NotSupportedException before any call.

Capability Supported
entity yes a launch's UUID (launch:, launchlibrary:, its API address); never read by its shape alone (OBIS's records are UUIDs too): a bare UUID is read as LL2's by this source
search yes LL2's search over name, mission, rocket and provider, paged by offset, total LL2's count; a domain other than other answers an empty page
series no
products no
occurrences yes the launches of a period, each at its pad, oldest first by default (newest too), 100 a page at most; no place: LL2 filters by no box nor circle
datasets no
jobs no
open no
structure no
cross_references no none: LL2 gives Wikipedia links only
forecast no
historical no
area no a place is refused before any call: narrow by location (LL2's launch site ids)
station no
cloud_cover no

Which API

Launch Library 2, version 2.3.0 (https://ll.thespacedevs.com/2.3.0/, its OpenAPI at schema/): launches/<id>/ and launches/?..., always in mode=normal (the pad with its coordinates, the rocket's configuration, the mission and its orbit; detailed adds the provider's and the rocket's statistics, 100 kB a launch). 15 calls an hour without a key (api-throttle/ tells the use).

Method Reads Calls
entity() a launch's UUID, launch:..., launchlibrary:..., its API address launches/<id>/?mode=normal; 404 is null
search() Query::$text (LL2's search: name, mission, rocket, provider), a domain other than other answers nothing launches/?search=&limit=&offset=
occurrences() a period (both ends included, an end at midnight its whole day; open ends allowed), filters, sort oldest (default) or newest, limit (100 at most), cursor launches/?net__gte=&net__lte=&ordering=net|-net&...

Occurrences: each launch has its time (NET, UTC) and its place (the pad's latitude and longitude). LL2 filters by no box nor circle, so a query that names a place is refused before any call (no area capability, and no answer filtered by hand: the pages would lie); narrow by launch site with location instead. Filters (each refused before any call when unknown):

Key LL2 Value
provider lsp__name the provider's name: SpaceX, China Aerospace Science and Technology Corporation
rocket rocket__configuration__full_name__icontains a part of the rocket's full name: Falcon 9
location location__ids LL2's launch site ids (12 Cape Canaveral SFS): one or a list
crewed is_crewed true, false
status status__ids LL2's status ids (3 success, 4 failure, 7 partial failure...): one or a list
orbit mission__orbit__name__icontains a part of the orbit's name: Low Earth, Sun-Synchronous

Paging by offset (Page::$next), total LL2's count. No shared key (country, kind...) is read: LL2's launch list filters by no country.

What an entity holds

id in the launchlibrary scheme, label LL2's name (Falcon 9 Block 5 | Crew-13), domain other (the core has no spaceflight domain), kind launch, description the mission's, url its API record (LL2 has no page of its own), image LL2's picture (its credit and licence in LL2), time, place, and: status, status_code, net, net_precision (Second, Minute, Hour, Day, Month, Quarter...), window_start, window_end, probability (%, the weather's), failure_reason, provider, provider_type, rocket, mission, mission_type, orbit, pad, location, location_id, country (ISO 3166-1 alpha-2), webcast_live, orbital_launch_attempt_count_year. No identifier of another base (LL2 gives Wikipedia links only), no related.

What LL2 does not give here

Events, astronauts, spacecraft, space stations, expeditions, dockings, agencies, launchers and landings (each an endpoint of LL2), the detailed mode's statistics, the timelines, the updates, the videos, and the Spaceflight News API.

Example

<?php

require __DIR__.'/vendor/autoload.php';

use Omnilab\Launches\LaunchesSourceFactory;
use Omnilab\Source\OccurrenceQuery;
use Symfony\Component\HttpClient\HttpClient;

$launches = (new LaunchesSourceFactory(HttpClient::create()))->create(['mailto' => 'you@example.org']);   // 15 calls an hour without a key

$page = $launches->occurrences(new OccurrenceQuery(null, new DateTimeImmutable('2026-10-20'), new DateTimeImmutable('2026-10-26'), limit: 4));
printf("%d launches from 2026-10-20 to 10-26; the first %d:\n", $page->total, count($page));
foreach ($page as $launch) {
    printf("  %s UTC  %-45s %s, %s\n", $launch->time->format('Y-m-d H:i'), $launch->label, $launch->value('status'), $launch->value('location'));
}
7 launches from 2026-10-20 to 10-26; the first 4:
  2026-10-20 11:04 UTC  Falcon 9 Block 5 | Bandwagon 5 (Dedicated Mid-Inclination Rideshare) Launch Successful, Cape Canaveral SFS, FL, USA
  2026-10-21 03:39 UTC  Ceres-1S | Xiguang-4 01                       Launch Successful, Haiyang Oriental Spaceport
  2026-10-23 07:11 UTC  Electron | We're Not Hawking Around (3x HawkEye 360) Launch Successful, Rocket Lab Launch Complex 1, Mahia Peninsula, New Zealand
  2026-10-23 10:15 UTC  Long March 6A | Yaogan 50-03                  Launch Successful, Taiyuan Satellite Launch Center, People's Republic of China

(as answered on 2026-10-27: one call). SpaceX's crewed launches would be [... filters: ['provider' => 'SpaceX', 'crewed' => true]].

# config/packages/omnilab.yaml
omnilab:
    sources:
        launches: { factory: launches, options: { mailto: '%env(OMNILAB_MAILTO)%', api_key: '%env(default::LL2_API_KEY)%' } }

Errors

Every call goes through HttpSource: a 404 or a 410 (and a 204) is null - an empty page for a list -; a 429 is a RateLimitedException (retryAfter from Retry-After); a 5xx, a time-out or a host that does not answer an UnavailableException; any other 4xx a ProviderException with its status and what the service said; an answer that is not JSON a ProviderException, a web page answered for JSON an UnavailableException.

Before any call (NotSupportedException): an identifier that is no launch's, a place in an occurrence query, a filter key not read, a sort other than newest and oldest. Past 15 calls an hour without a key LL2 answers 429: a RateLimitedException, with retryAfter when LL2 says. An unknown id is LL2's 404, null.

Verified, and not

Against the real service on 2026-10-15 and 2026-10-16: Crew-13 by its id (4.1 s), the launches of 1 to 14 October 2026 (nine, in two pages of five), SpaceX's crewed launches from 1 September 2026 (one), the searches for Artemis (eight) and Starship (27), an unknown id (404); the throttle endpoint (15 an hour). The fixtures in Tests/Fixtures/ are its answers.

Again on 2026-10-27: the launches of 20 to 26 October 2026 (seven, four a page; the example above), one call.

Not verified: the 429 met (the fixture is written after LL2's documented answer; the run stayed under the limit); a key (none was obtained); every filter's live effect beyond provider and crewed.

Responsibility

This package is an independent, unofficial client: it is not affiliated with, endorsed by or sponsored by The Space Devs. Launch Library 2 is free within its rate limit; The Space Devs ask that development use their development server and that Launch Library 2 be credited as the source, each image carrying its own credit and licence, as the README's Terms of use says. Whoever runs the package is responsible for complying with them and for any use made of what it returns: see the README's Responsibility section.

Proposer une modification docs/index.md