Quickstart — TypeScript SDK
The same "list telescopes, draft an observation, publish" walkthrough as the curl quickstart, using the in-tree TypeScript SDK.
Prereqs
- Node 20+.
- A way to install
skynet-sdk— either as an npm workspace dependency in this monorepo, or via a local-checkout install (the SDK isn't published to npm; see TypeScript SDK). - An access token. See Auth.
Setup
import {
Client,
MeApi,
TelescopesApi,
ObservingAccountsApi,
ObservationsApi,
ObservationRequestsApi,
TargetsApi,
} from 'skynet-sdk';
const client = new Client({
baseUrl: 'https://api.skynetgo.org/v1',
token: process.env.SKYNET_TOKEN!, // bearer token
});
const me = new MeApi(client);
const telescopes = new TelescopesApi(client);
const accounts = new ObservingAccountsApi(client);
const observations = new ObservationsApi(client);
const requests = new ObservationRequestsApi(client);
const targets = new TargetsApi(client);
If you need refresh-token rotation, wrap token in an async
provider when constructing Client — the SDK calls the provider
on every request so a single refresh refreshes future calls too.
Walkthrough
async function main() {
// 1. Who am I?
const user = await me.get();
console.log(`Hello, ${user.firstName} ${user.lastName}`);
// 2. List telescopes
const telescopePage = await telescopes.list({ size: 10 });
console.log(`${telescopePage.total} telescopes visible to you`);
for (const t of telescopePage.items.slice(0, 5)) {
console.log(` - ${t.name} (id=${t.id}, slug=${t.slug})`);
}
// 3. Pick an observing grant
const accountPage = await accounts.list({ ownerId: user.id });
const account = accountPage.items[0];
const grant = account.observingGrants[0]; // structure may differ
console.log(`Using account ${account.name}, grant ${grant.id}`);
// 4. Create a draft observation
const observation = await observations.create({
name: 'TS Quickstart M51',
ownerId: user.id,
kind: 'draft',
iterations: 1,
priority: 50,
});
console.log(`Draft observation ${observation.id} created`);
// 5. Set the target
await targets.upsertForObservation(observation.id, {
name: 'M51',
position: {
positionType: 'fixed',
frame: 'equatorial',
ra: 202.4696,
dec: 47.1952,
},
});
// 6. Add an imaging request
await requests.create({
observationId: observation.id,
requestType: 'opticalImaging',
iterations: 1,
filterTypes: ['V'],
exposureMode: 'time',
exposureTime: 60.0,
});
// 7. Attach the grant
await observations.addObservingGrant(observation.id, {
observingGrantId: grant.id,
});
// 8. Publish
const published = await observations.publish(observation.id);
console.log(`Published as ${published.kind} (id=${published.id})`);
// 9. Poll
for (let i = 0; i < 5; i++) {
await new Promise(r => setTimeout(r, 20_000));
const obs = await observations.get(observation.id);
console.log(`${i}: status=${obs.status} progress=${obs.progress}`);
}
}
main().catch(err => {
console.error('Failed:', err);
process.exit(1);
});
Notes
- Method names above are illustrative — the exact names depend
on the generated openapi-typescript bindings. Look at
packages/ts/skynet-sdk/src/apis/for the canonical method set per resource. - Wire format is camelCase —
requestType: 'opticalImaging', notrequest_type: 'optical_imaging'. See Conventions. - Polymorphic resources use discriminators (
requestType,positionType, etc.); the TS types are discriminated unions so TypeScript narrows the concrete shape automatically when you switch on the discriminator. - For typed coordinate math (Julian date, frame conversions,
precession),
skynet-sdk/coordsprovides browser-friendly utilities — useful when you're computing positions client-side.
Errors
The SDK rejects non-2xx responses. Catch the rejection and switch on the status:
try {
await observations.publish(observation.id);
} catch (err) {
if (err.status === 422) {
console.log('Validation failed:', err.body.detail);
} else if (err.status === 403) {
console.log('Token missing the right scope');
} else {
throw err;
}
}
Next steps
- For realtime subscriptions, see WebSocket streams.
- For the Python equivalent, see quickstart — Python SDK.