Skip to content

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 camelCaserequestType: 'opticalImaging', not request_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/coords provides 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