Quickstart — Python SDK
Same walkthrough as the curl quickstart and
the TS SDK quickstart, using the Python
SDK's shared schemas with httpx for HTTP.
The Python SDK ships typed Pydantic schemas; it doesn't yet ship a
generated HTTP client. The pattern most Skynet Python consumers use
is httpx + the SDK schemas — that's what we'll do here.
Prereqs
- Python 3.10+ and a way to install
skynet-sdk(in-tree via uv, or a local-checkout install — see Python SDK). pip install httpx pydantic(or use the SDK's already-installed deps).- An access token. See Auth.
Setup
import os
import httpx
from skynet_sdk.schemas import (
Observation,
ObservationRequest,
Target,
FixedPosition,
)
from skynet_sdk.enums import (
DeviceType,
InstrumentTaskExecutionState,
)
API = "https://api.skynetgo.org/v1"
TOKEN = os.environ["SKYNET_TOKEN"]
client = httpx.Client(
base_url=API,
headers={"Authorization": f"Bearer {TOKEN}"},
timeout=30.0,
)
Walkthrough
def main() -> None:
# 1. Who am I?
me = client.get("/me").raise_for_status().json()
print(f"Hello, {me['firstName']} {me['lastName']}")
# 2. List telescopes
telescopes = client.get("/telescopes", params={"size": 10}).raise_for_status().json()
print(f"{telescopes['total']} telescopes visible")
for t in telescopes["items"][:5]:
print(f" - {t['name']} (id={t['id']}, slug={t['slug']})")
# 3. Pick an observing grant
accounts = client.get(
"/observing-accounts",
params={"ownerId": me["id"]},
).raise_for_status().json()
account = accounts["items"][0]
grant = account["observingGrants"][0]
# 4. Create a draft observation
obs = client.post("/observations", json={
"name": "Py Quickstart M51",
"ownerId": me["id"],
"kind": "draft",
"iterations": 1,
"priority": 50,
}).raise_for_status().json()
obs_id = obs["id"]
print(f"Draft observation {obs_id} created")
# 5. Set the target
client.patch(f"/observations/{obs_id}/target", json={
"name": "M51",
"position": {
"positionType": "fixed",
"frame": "equatorial",
"ra": 202.4696,
"dec": 47.1952,
},
}).raise_for_status()
# 6. Add an imaging request
client.post(f"/observations/{obs_id}/requests", json={
"requestType": "opticalImaging",
"iterations": 1,
"filterTypes": ["V"],
"exposureMode": "time",
"exposureTime": 60.0,
}).raise_for_status()
# 7. Attach the grant
client.post(f"/observations/{obs_id}/observing-grants", json={
"observingGrantId": grant["id"],
}).raise_for_status()
# 8. Publish
published = client.post(f"/observations/{obs_id}/publish").raise_for_status().json()
print(f"Published as {published['kind']} (id={published['id']})")
if __name__ == "__main__":
main()
Why not a generated client?
The TS SDK leans on openapi-typescript to auto-generate typed
clients from /openapi.json. There's no equivalent in the Python
SDK today — most Python integrations either use httpx directly
(as above) or use the WebSocket protocol for streaming work where
the schemas are the bigger win than a generated HTTP client.
If a generated Python client would help you, flag it. The OpenAPI
spec is already served at /openapi.json so the tooling step is
straightforward.
Validating responses with the SDK schemas
When you want type safety on the response side, validate against the SDK's Pydantic models:
raw = client.get(f"/observations/{obs_id}").raise_for_status().json()
observation = Observation.model_validate(raw)
print(observation.name, observation.status)
For polymorphic responses (Device, Instrument, ObservationRequest, …), use the base type's validator — Pydantic picks the concrete subclass from the discriminator:
from skynet_sdk.schemas import Device
devices = client.get("/devices").raise_for_status().json()
for raw_device in devices["items"]:
device = Device.model_validate(raw_device) # concrete: Camera, Mount, …
print(device.device_type, device.id)
Coordinate math
For coordinate transforms and ephemerides, the Python SDK exposes
ephem:
from skynet_sdk.ephem import target_position, visibility
These wrap astropy.coordinates for the patterns Skynet uses
internally. For ad-hoc coordinate work, use astropy directly.
Next steps
- For realtime subscriptions, see WebSocket streams.
- For the TS equivalent, see quickstart — TypeScript SDK.