NAV
shell python

Tasking API - v2.2.1

The Spire Tasking API is the direct interface for scheduling windows in the Spire constellation. It can be used directly for manual scheduling of individual windows or, more commonly, as a service for automated scheduling systems.

Auto-generated OpenAPI specification

Important Notes

Minimum Window Padding

Certain startup and shutdown procedures occur before and after window execution. Windows should not be scheduled too close together or some operations may not complete successfully.

window type pre-buffer post-buffer
LEASE_ADCS 420s 420s
LEASE_ISL 60s 60s
MAINTENANCE 0s 0s
PAYLOAD_CORAL 300s 150s
PAYLOAD_DEXTER 220s 265s
PAYLOAD_IPI 120s 210s
PAYLOAD_MARSUPIAL 300s 150s
PAYLOAD_MYRIAD 300s 150s
PAYLOAD_NANO 300s 150s
PAYLOAD_SABERTOOTH 180s 210s
PAYLOAD_SDR 120s 210s

Post-Upload Windows

When uploading a file to a payload, the file is held in a queuing area until the first window of a type associated with that payload is executed.

NOTE: This requirement is intended to be removed in a future release.

Minimum Window Duration

window type minimum duration (seconds)
LEASE_ADCS 60
LEASE_ISL 60
MAINTENANCE 60
PAYLOAD_CORAL 30
PAYLOAD_DEXTER No minimum
PAYLOAD_IPI 30
PAYLOAD_MARSUPIAL 30
PAYLOAD_MYRIAD 30
PAYLOAD_NANO 30
PAYLOAD_SABERTOOTH 30
PAYLOAD_SDR 30

Total Daily Download Volume

Users should limit total downloads to less than 100MB/day

Total Daily Upload Volume and Upload Limitations

Users should expect an average upload volume of roughly to 125KB/day (this can be increased by designating a satellite to prioritize uploads, though this may impact download times). The upper limit on individual upload file size is 10MB. There is an option to manually pre-load larger file packages to a satellite prior to launch if the contract involves a satellite in active assembly.

Upload and Download Time Expectations

Upload Times

Please note that uploading a file requires the satellite in question to complete at least one bidirectional contact over a Spire ground station. Depending on a satellite's upcoming contact schedule, even a small file (on the order of kb) can take up to 6 hours from the requested time to successfully upload. As Spire schedules at minimum one bidirectional pass per 6 hour period, upload times will generally be faster than the worst case scenario. The larger the file, the greater the necessary contact time.

Download Times

Depending on the difference in time between the end of a payload window and the next scheduled contact, file download times can range between the order of minutes to several hours. If a contract with Spire has specific latency requirements, Spire's engineers will work to facilitate a means of ensuring consistent download times.

Spire's satellites utilize an Sband Radio for their most efficient downloads.

ADCS Priority

It is possible that multiple windows can be scheduled simultaneously that request certain ADCS modes / orientations. While it is not desirable to do this, it is not explicitly prohibited. As such there are certain priorities associated with windows to determine which one takes effect.

All standard payload windows, that allow for adcs_config to be specified, have the same priority. This means that, when multiple windows overlap, the one starting latest will ultimately take effect. Non-standard payload windows that command the ADCS system include LEASE_ADCS and LEASE_ISL.

LEASE_ADCS windows have a higher priority than all standard payload windows since a payload can be commanding the mode/orientation continuously throughout the course of the window. LEASE_ISL windows, since they require pointing the satellite towards its paired ISL satellite, is higher priority than both standard payload windows and LEASE_ADCS windows. For satellites that require stationkeeping, drag/propulsion operations may be scheduled by Spire to do so. These operations will always have the highest priority over the ADCS system.

Thus the order of priority, highest to lowest, is as follows:

  1. Stationkeeping operations
  2. LEASE_ISL
  3. LEASE_ADCS
  4. All standard payload windows (latest one wins)

Overlapping Windows

By default no scheduled window can overlap with another window, whether that is a payload window, or a contact window that Spire uses for maintenance of the satellite.

There are some use cases, however, that involve overlapping two windows. An example of this might be analyzing some signals captured on the SDR payload, which would trigger an image capture on the IPI payload.

In order to allow for certain use cases, some explicit window overlappings are allowed. Also note that, more than two windows can overlap if each window type is allowed to overlap with each of the other window types. For example, PAYLOAD_SDR, PAYLOAD_SABERTOOTH, and PAYLOAD_IPI can all be scheduled at the same time.

The following pairs of windows are allowed to overlap:

Background

Scheduling

The Spire constellation is controlled via a globally synchronized calendar of fixed-duration operation windows. Each window has a fixed start time, a fixed duration, a type, and additional window-specific parameters that tune its operation.

A single window may consist of multiple steps that are scheduled together e.g. the PAYLOAD_SDR task can orient the satellite, record an IQ file, and perform an analysis of the recorded IQ file in one schedulable unit.

The canonical schedule is stored in Spire-controlled terrestrial infrastructure. Relevant windows are synchronized to each satellite during regular maintenance procedures and executed by each satellite's onboard controller.

Executing User Code

Execution of a window may require execution of user code on the satellite. Each payload maintains a persistent per-user filesystem "sandbox". User-supplied executables are run with this sandbox as the root filesystem.

  1. Any files generated during pre-user code execution phases will be written to deterministic locations in /inbox (see particular window types for details)
  2. Any files written to /outbox will be queued for download and delivery to customer at the end of the window
  3. /inbox and /outbox are cleared between windows. Files written elsewhere will persist between window executions and may be used for staging data for transfer and processing on other payloads e.g. Sabertooth-generated waveforms for transmission on Dexter SDR or for followup operations.
  4. The stdout/stderr from a given executable will not be downloaded automatically, but can be included in the execute logs of a script by using "exec" as shown on the right.
#!/bin/bash

exec > /outbox/a_timestamped_filename
exec 2>&1

# script goes here
...

Note that within the "sandbox" filesystem, system folders cannot be uploaded to, as they mount to system libraries used by Spire. Please refrain from uploading to any "destination_path" starting in the following paths:

API Standards

All responses to the API will be returned as JSON.

Successful requests will have a "data" parameter containing the results of the API call.

If the request fails, the returned JSON will have a "fault" parameter containing a dictionary with a "faultstring" parameter pointing to a string description of the error. The dictionary MAY also contain a "detail" key with additional details regarding the error. The contents of the faultstring and detail field(s) are intended for human analysis and should not be used by automated systems.

{ "fault":
    { "faultstring": "Failed to resolve API Key variable token",
        "detail": {
            "errorcode": "steps.oauth.v2.FailedToResolveAPIKey"
        }
    }
}

Data Delivery

Spire maintains a minimum retention policy for customer data. All data files generated on behalf of a customer are published directly to the customer's specified S3 bucket and then deleted from Spire systems.

To enable delivery, the customer will need to add cross-account access to the desired S3 bucket for Spire. Spire will provide detailed instructions as part of initial customer signup.

Authentication

API

Before accessing the APIs you will need an API key to authenticate against the API. This will be provided during signup.

The Tasking API uses bearer tokens to authenticate requests. Attempting to make requests to the API without a valid API Key will result in the return of an HTTP 401 "Not Authorized" response with a JSON payload containing an error message.

To ensure transport layer security, all access or communication with the APIs must be made over HTTPS.

Example Usage

In this section we will walk through tasking the constellation to orient towards a target on the ground, record radio frequency from that target, process that recording, and queue the results for download. Once downloaded, files will appear in the customer's S3 bucket.

NOTE: The Python used in these examples uses some f-string types, and thus requires a Python version of 3.6 or higher.

Authenticate

First, we set the authentication token that identifies the user and is passed to every request to the API.

HOST="https://api.orb.spire.com"
AUTH_HEADER="Authorization: Bearer YOUR_AUTH_TOKEN"
# setup for all further examples
import requests

host = 'https://api.orb.spire.com'
your_auth_token = 'EXAMPLEAUTHTOKEN'
auth = { 'Authorization': f'Bearer {your_auth_token}' }

Select satellite

To start the tasking process, we retrieve the list of taskable satellites and their supported window types. This step can be skipped if the desired satellite is already known.

We see here that FM123 has the desired capabilities (PAYLOAD_SDR is supported).

curl -X GET -H "${AUTH_HEADER}" "${HOST}/tasking/satellites"
api = host + '/tasking/satellites'
r = requests.get(api, headers=auth)
r.raise_for_status()
r.json()
{
  "data": [{
    "id": "FM123",
    "norad_id": "12345",
    "supported_windows": [
      "PAYLOAD_SDR",
      "PAYLOAD_SABERTOOTH",
    ]
  }]
}

Upload processing executable

We then upload the desired post-processing binary to the selected satellite. This can be skipped if the binary has previously been uploaded as uploads persist on the satellite.

NOTE: Any stdout/stderr of an executable will not automatically be downloaded. They can, however, be included in the execute logs by using "exec" in a given uploaded script.

The destination path of the uploaded executable will be used later when we reserve our SDR window. The server will respond to the request with a JSON payload containing the ID of the upload request. See the example JSON response to the right.

SATELLITE_ID="satellite_id=FM123"
PAYLOAD="payload=SDR"
DESTINATION_PATH="destination_path=/persist/bin/phase1"
EXECUTABLE="executable=true"
QUERY_PARAMS="${SATELLITE_ID}&${PAYLOAD}&${DESTINATION_PATH}&${EXECUTABLE}"

# Create test file to upload
echo "test" > phase1

curl -X POST "${HOST}/tasking/upload?${QUERY_PARAMS}" \
-H "${AUTH_HEADER}"  \
-F "file=@phase1"
api = host + '/tasking/upload'
files = { 'file': open('phase1', 'rb') }
params = {
    'satellite_id': 'FM123',
    'payload': 'SDR',
    'destination_path': '/persist/bin/phase1',
    'executable': True
}
r = requests.post(api, headers=auth, params=params, files=files)
r.raise_for_status()
r.json()
{"data": {"id": "8f76a939-609e-4042-8c97-079031af0320"}}

Check upload progress

Once submitted, the constellation will upload the requested file over subsequent contact(s). To check on the status of the upload we can make a GET request on the /upload endpoint.

Once the executable has successfully been uploaded to the satellite the response will have status "UPLOADED". See the example JSON response to the right.

curl -X GET -H "${AUTH_HEADER}" "${HOST}/tasking/uploads"
api = host + '/tasking/uploads'
r = requests.get(api, headers=auth)
r.raise_for_status()
r.json()
{
  "data": [
    {
      "satellite_id": "FM123",
      "payload": "SDR",
      "destination_path": "/persist/bin/phase1",
      "executable": true,
      "status": "UPLOADED",
      "id": "71c92e3c57bc440ea89d76c94cdf387f",
    }
  ]
}

Look for available time slot

With the desired analysis script on the satellite, the PAYLOAD_SDR window can be scheduled. To discover when the satellite is available for tasking, the /availability endpoint is used. Here we check for times the satellite is available for tasking during a 24 hour period.

This will return a list of periods when the satellite can be tasked for this operation. See the example JSON response to the right.

SATELLITE_ID="satellite_id=FM123"
WINDOW_TYPE="window_type=PAYLOAD_SDR"
START="start=$(date -u +%s)"
DURATION="duration=86400"  # One day
QUERY_PARAMS="${SATELLITE_ID}&${WINDOW_TYPE}&${START}&${DURATION}"

curl -X GET -H "${AUTH_HEADER}" "${HOST}/tasking/availability?${QUERY_PARAMS}"
import time
api = host + '/tasking/availability'
params = {
    'satellite_id': 'FM123',
    'window_type': 'PAYLOAD_SDR',
    'start': int(time.time()),
    'duration': 24 * 60 * 60
}
r = requests.get(api, headers=auth, params=params)
r.raise_for_status()
r.json()
{
  "data": {
    "available": [
      { "start": 1599445000, "end": 1599473800 },
      { "start": 1599474400, "end": 1599503200 },
      { "start": 1599503800, "end": 1599531400 }
    ]
  }
}

Schedule window

We now schedule the operation. We create a 10 minute PAYLOAD_SDR window with a 60 second IQ capture over the Bermuda Triangle. This analysis script analyzes this file and outputs a single file results.txt for download with an estimated file size is 10.5 kb.

The constellation will use the download size estimate to allocate contact time for download. If generated files are larger than the downlink budget, file retrieval latency may be affected.

The server will respond to the request with the ID of the scheduled window in a JSON payload. See the example JSON response to the right.

curl -X POST "${HOST}/tasking/window" \
-H "${AUTH_HEADER}" \
-H "Content-Type: application/json" \
-d @- << EOF
{
    "type": "PAYLOAD_SDR",
    "satellite_id": "FM123",
    "start": 1599445000,
    "duration": 600,
    "parameters": {
        "downlink_budget": 10.5,
        "adcs_config": {
            "mode": "NADIR",
            "aperture": "VHF"
        },
        "user_command": {
            "executable": "/persist/bin/phase1",
            "executable_arguments": [
                "--cap-time", "60",
                "--output", "/outbox/results.txt"
            ]
        }
    }
}
EOF
api = host + '/tasking/window'
json = {
    'type': 'PAYLOAD_SDR',
    'satellite_id': 'FM123',
    'start': 1599445000,
    'duration': 600,
    'parameters': {
        'downlink_budget': 10.5,
        'adcs_config': {
            'mode': 'NADIR',
            'aperture': 'VHF',
        },
        'user_command': {
            'executable': '/persist/bin/phase1',
            'executable_arguments': [
                '--cap-time', '60',
                '--output', '/outbox/results.txt'
            ]
        }
    }
}
r = requests.post(api, headers=auth, json=json)
r.raise_for_status()
r.json()
{"data": {"id": "3014288"}}

Receive data

After the window successfully completes, the results.txt file written to /outbox will be automatically downloaded and, once received, will be pushed directly to the customer's specified S3 bucket.

API Endpoints

GET /satellites

curl -X GET -H "${AUTH_HEADER}" "${HOST}/tasking/satellites"
api = host + '/tasking/satellites'
r = requests.get(api, headers=auth)
r.raise_for_status()
r.json()
{
  "data": [{
    "id": "FM123",
    "norad_id": "12345",
    "supported_windows": [
        "PAYLOAD_SDR",
        "PAYLOAD_SABERTOOTH"
    ],
    "supported_payloads: [
        "SDR",
        "SABERTOOTH"
    ]
  }]
}

Returns all taskable satellites and their supported window types and payloads. See the example JSON response to the right.

GET /availability

api = host + '/tasking/availability'
params = {
    'satellite_id': 'FM123',
    'window_type': 'PAYLOAD_SDR',
    'start': 1599445000,
    'duration': 24 * 60 * 60
}
r = requests.get(api, headers=auth, params=params)
r.raise_for_status()
r.json()
SATELLITE_ID="satellite_id=FM123"
WINDOW_TYPE="window_type=PAYLOAD_SDR"
START="start=$(date -u +%s)"
DURATION="duration=86400"  # One day
QUERY_PARAMS="${SATELLITE_ID}&${WINDOW_TYPE}&${START}&${DURATION}"

curl -X GET -H "${AUTH_HEADER}" "${HOST}/tasking/availability?${QUERY_PARAMS}"
{
  "data": {
    "available": [
      { "start": 1599445000, "end": 1599473800 },
      { "start": 1599474400, "end": 1599503200 },
      { "start": 1599503800, "end": 1599531400 }
    ]
  }
}

Return time ranges between start and end during which the user may schedule a window of the specified type. See the example JSON response to the right.

Arguments

Name Type Required Description
satellite_id string yes
window_type string yes See Supported Windows
start integer yes epoch time
duration integer yes seconds
paired_satellite_id string no For window types that involve a pair of satellites (such as LEASE_ISL) this is the other satellite's satellite_id

Response

Name Type Description
available list list of periods window can be scheduled within

POST /upload

SATELLITE_ID="satellite_id=FM123"
PAYLOAD="payload=SABERTOOTH"
DESTINATION_PATH="destination_path=/persist/bin/phase1"
EXECUTABLE="executable=true"
QUERY_PARAMS="${SATELLITE_ID}&${PAYLOAD}&${DESTINATION_PATH}&${EXECUTABLE}"

# Create test file to upload
echo "test" > phase1

curl -X POST "${HOST}/tasking/upload?${QUERY_PARAMS}" \
-H "${AUTH_HEADER}"  \
-F "file=@phase1"
api = host + '/tasking/upload'
files = { 'file': open('phase1', 'rb') }
params = {
    'satellite_id': 'FM123',
    'payload': 'SABERTOOTH',
    'destination_path': '/persist/bin/phase1',
    'executable': True
}
r = requests.post(api, headers=auth, params=params, files=files)
r.raise_for_status()
r.json()
{"data": {"id": "8f76a939-609e-4042-8c97-079031af0320"}}

Submit a file for upload to target satellite. The response is a JSON payload containing the ID of the upload request. See the example JSON response to the right.

No assumptions should be made regarding the structure of the ID.

Arguments

Name Type Required Description
satellite_id string yes
payload string yes See Supported Payloads
destination_path string yes path on payload
executable boolean yes
file multipart-encoded file yes
itar boolean no ITAR-tagged uploads will only be uploaded through US-based ground stations (default: false)

GET /uploads

Returns information on files previously submitted for uploading. See the example JSON response to the right.

curl -X GET -H "${AUTH_HEADER}" "${HOST}/tasking/uploads"
api = host + '/tasking/uploads'
r = requests.get(api, headers=auth)
r.raise_for_status()
r.json()
{
  "data": [
    {
      "satellite_id": "FM123",
      "payload": "SDR",
      "destination_path": "/persist/bin/phase1",
      "executable": true,
      "status": "PENDING",
      "id": "71c92e3c57bc440ea89d76c94cdf387f",
      "progress": 0,
      "last_update": 1659700499.978814
    },
    {
      "satellite_id": "FM123",
      "payload": "SABERTOOTH",
      "destination_path": "/persist/bin/phase2",
      "executable": true,
      "status": "UPLOADING",
      "id": "796392e80df14f46b07b86e13d3240ec",
      "progress": 13.33456773,
      "last_update": 1659702459.978814
    },
    {
      "satellite_id": "FM123",
      "payload": "SDR",
      "destination_path": "/persist/config/fir.txt",
      "executable": false,
      "status": "UPLOADED",
      "id": "45c59b08df97477a84af75ca2882859a",
      "progress": 100,
      "last_update": 1659730499.938517
    }
  ]
}

Additional Response Fields

Name Type Description
id string identifer for upload
status string "PENDING", "UPLOADING", or "UPLOADED"
last_update float timestamp of the last time the record has been updated (file has started/finished uploading, or a new segment has been uploaded)
progress float Current file progress (in percent)

POST /window

curl -X POST "${HOST}/tasking/window" \
-H "${AUTH_HEADER}" \
-H "Content-Type: application/json" \
-d @- << EOF
{
    "type": "PAYLOAD_SABERTOOTH",
    "satellite_id": "FM123",
    "start": 1599503800,
    "duration": 600,
    "parameters": {
        "downlink_budget": 0,
        "user_command": {
            "executable": "/persist/bin/generate_waveform",
            "executable_arguments": [
                "--period", "100",
                "--amplitude", "200"
            ]
        }
    }
}
EOF
api = host + '/tasking/window'
json = {
    'type': 'PAYLOAD_SABERTOOTH',
    'satellite_id': 'FM123',
    'start': 1599503800,
    'duration': 600,
    'parameters': {
        'downlink_budget': 0,
        'user_command': {
            'executable': '/persist/bin/generate_waveform',
            'executable_arguments': [
                '--period', '100',
                '--amplitude', '200'
            ]
        }
    }
}
r = requests.post(api, headers=auth, json=json)
r.raise_for_status()
r.json()
{"data": {"id": "3014288"}}

Schedule a new operation window. Each window type supports specific tuning arguments via the parameters field. The set of available payload window types and their supported parameters can be found at Supported Windows.

The server will respond to the request with the ID of the scheduled window in a JSON payload. See the example JSON response to the right.

No assumptions should be made regarding the structure of the ID.

Note that if a window is meant to have a paired window scheduled on a paired satellite (e.g. LEASE_ISL), it will be automatically scheduled, as well.

Arguments

Name Type Required Description
type string yes See Supported Windows
satellite_id string yes
start integer yes epoch time
duration integer yes seconds
parameters parameters yes See parameters

Additional Response Fields

Name Type Description
id string identifier for window

GET /contacts

SATELLITE_ID="satellite_id=FM123"
START_LT="start_lt=1648684800" # 2022-03-31 00:00 UTC
QUERY_PARAMS="${SATELLITE_ID}&${START_LT}"


curl -X GET -H "${AUTH_HEADER}" "${HOST}/tasking/contacts?${QUERY_PARAMS}"
api = host + '/tasking/contacts'
params = { 'satellite_id': 'FM123', start_lt: 1648684800} # 2022-03-31 00:00 UTC
r = requests.get(api, headers=auth, params=params)
r.raise_for_status()
r.json()
# If more values are available, `next` will contain the URL to the next page
{
  "data": [{
        "id": "5f7770a7984c4b30856a3a810c1b3e2f",
        "type": "BIDIR",
        "satellite_id": "FM123",
        "state": "PENDING_SYNC",
        "start": 1599503800,
        "duration": 600,
      },
      ...
  ],
  "next": "https://api.orb.spire.com/tasking/contacts?satellite_id=FM123&start_lt=1599553800"
}

# If there are no more values available, `next` will be null
{
  "data": [{
        "id": "5f7770a7984c4b30856a3a810c1b3e2f",
        "type": "BIDIR",
        "satellite_id": "FM123",
        ...
      }
  ],
  "next": null
}

List the latest contacts for a given satellite. The json object returned has two elements:

See the example JSON response to the right.

Valid statuses

Status Description
PENDING_SYNC The contact has been accepted by the API but not yet transferred to the satellite
SYNCED The contact has been transferred to the satellite

Valid types

Status Description
BIDIR The contact involves two-way transmissions between the satellite and a receiver
TXO The contact involves only one-way satellite to receiver transmissions
RXO The contact involves only one-way receiver to satellite transmissions

Arguments

Name Type Required Description
satellite_id string yes
start_lt float (epoch timestamp) no An "upper" bound, returns all contacts with start time less than the provided epoch. May be used with or without the start_gt argument
start_gt float (epoch timestamp) no A "lower" bound, returns all contacts with start time greater than the provided epoch. May be used with or without the start_lt argument

Additional Response Fields

Name Type Description
id string identifier for contact

GET /windows

SATELLITE_ID="satellite_id=FM123"
PLW_START_LT="plw_start_lt=1648684800" # 2022-03-31 00:00 UTC
QUERY_PARAMS="${SATELLITE_ID}&${PLW_START_LT}"


curl -X GET -H "${AUTH_HEADER}" "${HOST}/tasking/windows?${QUERY_PARAMS}"
api = host + '/tasking/windows'
params = { 'satellite_id': 'FM123', plw_start_lt: 1648684800} # 2022-03-31 00:00 UTC
r = requests.get(api, headers=auth, params=params)
r.raise_for_status()
r.json()
# If more values are available, `next` will contain the URL to the next page
{
  "data": [{
        "id": "5260382",
        "type": "PAYLOAD_SABERTOOTH",
        "satellite_id": "FM123",
        "state": "PENDING_SYNC",
        "start": 1599503800,
        "duration": 600,
        "parameters": {
          "user_command": {
            "executable": "/persist/bin/generate_waveform.sh",
            "executable_arguments": [
              "--period", "100",
              "--amplitude", "200"
            ],
          }
        },
        "exit_status": null,
        "ran_duration": null,
      },
      ...
  ],
  "next": "https://api.orb.spire.com/tasking/windows?satellite_id=FM123&plw_start_lt=1599553800"
}

# If there are no more values available, `next` will be null
{
  "data": [{
        "id": "5f7770a7984c4b30856a3a810c1b3e2f",
        "type": "PAYLOAD_SABERTOOTH",
        "satellite_id": "FM123",
        ...
      }
  ],
  "next": null
}

List the latest windows for a given satellite. The json object returned has two elements:

See the example JSON response to the right.

Valid Synchronization States

Status Description
PENDING_SYNC The window has been accepted by the API but not yet transferred to the satellite
SYNCED The window has been transferred to the satellite
FAILED_SYNC The window has not been transferred to the satellite in time for execution and will not execute
PENDING_DELETION A request to delete the window has been accepted by the API but not yet confirmed
UNKNOWN The window is in an unknown state, contact a Spire representative to resolve

Once a window is in the PENDING_DELETION state, its interval is no longer considered unavailable, so it will be possible to schedule a new window overlapping this interval, provided other conditions for the new window are met.

Once deletion of the window is confirmed, it is no longer listed in the GET /windows response.

Arguments

Name Type Required Description
satellite_id string yes
plw_start_lt float (epoch timestamp) no An "upper" bound, returns all windows with start time less than the provided epoch. May be used with or without the plw_start_gt argument
plw_start_gt float (epoch timestamp) no A "lower" bound, returns all windows with start time greater than the provided epoch. May be used with or without the plw_start_lt argument

Additional Response Fields

Name Type Description Log Time
id string identifier for window Generated when window POST command is called to create a new window
exit_status string A success indicator for the given window, reading either "FAILED"/"SUCCESSFUL", and null if not yet logged Updated when associated logged telemetry is downloaded upon window completion
ran_duration float the delta between the observed payload power on and the initiated window end. "null" if not yet logged

GET /window

ID=5260382
QUERY_PARAMS="${WINDOW_ID}"


curl -X GET -H "${AUTH_HEADER}" "${HOST}/tasking/window?${QUERY_PARAMS}"
api = host + '/tasking/window'
params = { 'id': 5260382}
r = requests.get(api, headers=auth, params=params)
r.raise_for_status()
r.json()
# GET Window Return
{
  "data": {
    "id": "5260382",
    "type": "PAYLOAD_SABERTOOTH",
    "satellite_id": "FM123",
    "state": "SYNCED",
    "start": 1599503800,
    "duration": 600,
    "parameters": {
      "user_command": {
        "executable": "/persist/bin/generate_waveform.sh",
        "executable_arguments": [
          "--period", "100",
          "--amplitude", "200"
        ],
      }
    },
    "exit_status": "SUCCESSFUL",
    "ran_duration": 590.026757,
  }
}

List the synchronization information for a given satellite window, keyed off the requested window "id". The json object returned has the same structure as a given window element in the GET /windows return.

See the example JSON response to the right.

DELETE /window

ID="id=5f7770a7984c4b30856a3a810c1b3e2f"
QUERY_PARAMS="${ID}"

curl -X DELETE -H "${AUTH_HEADER}" "${HOST}/tasking/window?${QUERY_PARAMS}"
api = host + '/tasking/window'
params = { 'id': '5f7770a7984c4b30856a3a810c1b3e2f' }
r = requests.delete(api, headers=auth, params=params)
r.raise_for_status()
r.json()
{"data": {"id": "3014288"}}

Request for a window to be deleted. If the window is in a PENDING_SYNC or SYNCED state this will move it to the PENDING_DELETION state. The deletion request may be rejected if there is no opportunity to confirm deletion with the satellite. Once deletion is confirmed the window will no longer appear in the GET /windows response. If deletion cannot be confirmed the window may still execute. If the window has a paired window that was automatically scheduled on a paired satellite, the deletion of the paired window will be attempted during this request, too. Only both windows will be deleted if they both meet the deletion requirement outlined above.

If the request is successful, the endpoint will return the id of the deleted window.

Arguments

Name Type Required Description
id string yes identifier for window to delete

DELETE /upload

ID="id=796392e80df14f46b07b86e13d3240ec"
QUERY_PARAMS="${ID}"

curl -X DELETE -H "${AUTH_HEADER}" "${HOST}/tasking/upload?${QUERY_PARAMS}"
api = host + '/tasking/upload'
params = { 'id': '796392e80df14f46b07b86e13d3240ec' }
r = requests.delete(api, headers=auth, params=params)
r.raise_for_status()
r.json()
{"data": {"id": "796392e80df14f46b07b86e13d3240ec"}}

Remove a previously-requested upload from the upload queue.

If the specified file has already been uploaded to the satellite, an error will be throw.

If the upload is in progress, no further attempts to complete the file will be made.

If the request is successful, the endpoint will return the id of the deleted window.

Arguments

Name Type Required Description
id string yes identifier of upload to delete

GET /quota

START="start=1707782400" # 2024-02-13 00:00 UTC
DURATION="duration=10"
QUERY_PARAMS="${START}&${DURATION}"


curl -X GET -H "${AUTH_HEADER}" "${HOST}/tasking/quota?${QUERY_PARAMS}"
api = host + '/tasking/quota'
params = { 'start': 1707782400, 'duration': 10} # 2024-02-13 00:00 UTC
r = requests.get(api, headers=auth, params=params)
r.raise_for_status()
r.json()
{
  "data": {
    "quotas": [
      {
        "scope": "PER_SATELLITE",
        "resource": "TASKING_DURATION",
        "usage": 0.5,
        "quota": 1,
        "unit": "hour",
        "quota_start": 1707782400,
        "quota_end": 1707868799,
        "basis": "PER_DAY",
        "window_type": "PAYLOAD_SDR",
        "satellite_id": "FM123"
      },
      {
        "scope": "GLOBAL",
        "resource": "TASKING_DURATION",
        "usage": 0.5,
        "quota": 1,
        "unit": "hour",
        "quota_start": 1707782400,
        "quota_end": 1707868799,
        "basis": "PER_DAY",
        "window_type": "PAYLOAD_SDR"
      },
      {
        "scope": "PER_SATELLITE",
        "resource": "DATA_GENERATION_VOLUME",
        "usage": 0.2,
        "quota": 1,
        "unit": "GB",
        "quota_start": 1707782400,
        "quota_end": 1707868799,
        "basis": "PER_DAY",
        "window_type": "PAYLOAD_SDR",
        "satellite_id": "FM123"
      },
    ]
}

List the quota usage within an interval. Usage for each individual quota is returned for each quota "period" that overlaps with the request interval. Where a per-satellite quota exists, individual usage is detailed for each satellite. GLOBAL quotas are cummulative across satellites.

See the example JSON response to the right.

Arguments

Name Type Required Description
start integer yes epoch time
duration integer yes seconds

Additional Response Fields

Name Type Description
scope string "PER_SATELLITE", "GLOBAL"
resource string "TASKING_DURATION", "DATA_GENERATION_VOLUME"
usage float quota usage in the associated quota period
quota float quota allowance in the associated quota period
unit string unit of measurement of the usage and quota
quota_start string epoch time of the start of the quota period
quota_end string epoch time of the end of the quota period
basis string quota period basis - only "PER_DAY" is currently supported
window_type string if the quota is specific to a window type
satellite_id string if scope is "PER_SATELLITE"

Supported Payloads

A variety of payloads with different purposes are available on Spire satellites. A satellite contains a subset of all the possible payloads. The following payloads are available on Spire satellites:

Supported Windows

LEASE_ADCS

curl -X POST "${HOST}/tasking/window" \
-H "${AUTH_HEADER}" \
-H "Content-Type: application/json" \
-d @- << EOF
{
    "type": "LEASE_ADCS",
    "satellite_id": "FM123",
    "start": 1599445000,
    "duration": 600,
    "parameters": {
        "adcs_config": {
            "mode": "TRACKING",
            "aperture": "VHF",
            "target_latitude_north": 5.240337,
            "target_longitude_east": -52.768472
        }
    }
}
EOF
api = host + '/tasking/window'
json = {
    'type': 'LEASE_ADCS',
    'satellite_id': 'FM123',
    'start': 1599445000,
    'duration': 600,
    'parameters': {
        'adcs_config': {
            'mode': 'TRACKING',
            'aperture': 'VHF',
            'target_latitude_north': 5.240337,
            'target_longitude_east': -52.768472
        }
    }
}
requests.post(api, headers=auth, json=json)

The window is used to specify that customer applications on the payloads may command the ADCS system via the local Spire Linux Agent, which allows changing the satellites orientation. It can also specify an initial orientation. Documentation about the software interfaces to the on-board ADCS system can be found here.

Type

LEASE_ADCS

parameters

Name Type Required Description
adcs_config adcs_config yes See adcs_config

LEASE_ISL

curl -X POST "${HOST}/tasking/window" \
-H "${AUTH_HEADER}" \
-H "Content-Type: application/json" \
-d @- << EOF
{
    "type": "LEASE_ISL",
    "satellite_id": "FM123",
    "start": 1599445000,
    "duration": 600,
    "parameters": {
        "isl_receive_satellite_id": "FM124"
    }
}
EOF
api = host + '/tasking/window'
json = {
    'type': 'LEASE_ISL',
    'satellite_id': 'FM123',
    'start': 1599445000,
    'duration': 600,
    'parameters': {
        'isl_receive_satellite_id': 'FM124'
    }
}
requests.post(api, headers=auth, json=json)
{"data": {"id": "3014288", "paired_id": "3014289"}}

The window is used to enable an inter-satellite communication link so that processes on the payloads can use the ISL to send data to, or receive data from, another satellite. This window will be scheduled on the satellite which will be sending data and the satellite to receive those data is specified as a parameter. Documentation about the software interfaces to transmit and receive using the ISL system can be found here.

Type

LEASE_ISL

parameters

Name Type Required Description
isl_receive_satellite_id string yes The identifier for the satellite which will be receiving data from the satellite that this window is scheduled on.

Special POST /window Response

In the POST /window section, above, the response is noted as having a single ID returned. Since ISL windows come in pairs (i.e. one for each satellite involved), the POST /window endpoint will return a second ID. This will be the ID of the window created for the paired satellite. This will be found under an additional key, paired_id. See the example JSON response in this section.

PAYLOAD_DEXTER

curl -X POST "${HOST}/tasking/window" \
-H "${AUTH_HEADER}" \
-H "Content-Type: application/json" \
-d @- << EOF
{
    "type": "PAYLOAD_DEXTER",
    "satellite_id": "FM123",
    "start": 1599445000,
    "duration": 240,
    "parameters": {
        "user_command": {
            "executable": "dexter_program",
            "executable_arguments": [
                "--option1", "197821",
                "--option2", "502812"
            ]
        }
    }
}
EOF
api = host + '/tasking/window'
json = {
    'type': 'PAYLOAD_DEXTER',
    'satellite_id': 'FM123',
    'start': 1599445000,
    'duration': 240,
    'parameters': {
        'user_command': {
            'executable': 'dexter_program',
            'executable_arguments': [
                '--option1', '197821',
                '--option2', '502812'
            ]
        }
    }
}
requests.post(api, headers=auth, json=json)

A PAYLOAD_DEXTER window consists of a processing phase where a customer-supplied executable is run with customer supplied arguments.

Type

PAYLOAD_DEXTER

parameters

Name Type Required Description
user_command user_command yes See user_command

PAYLOAD_IPI

curl -X POST "${HOST}/tasking/window" \
-H "${AUTH_HEADER}" \
-H "Content-Type: application/json" \
-d @- << EOF
{
    "type": "PAYLOAD_IPI",
    "satellite_id": "FM123",
    "start": 1599445000,
    "duration": 600,
    "parameters": {
        "downlink_budget": 0,
        "copy_from": [
            {
                "src_payload": "SABERTOOTH",
                "src_path": "/persist/data/locations1",
                "dst_path": "/persist/data/locations1"
            }
        ],
        "adcs_config": {
            "mode": "TRACKING",
            "aperture": "IMAGER_TBD",
            "target_latitude_north": 5.240337,
            "target_longitude_east": -52.768472
        },
        "user_command": {
            "executable": "/persist/bin/capture",
            "executable_arguments": [
                "--duration", "60",
                "--interval", "10",
                "--output-dir-for-download", "/outbox/images/"
            ]
        }
    }
}
EOF
api = host + '/tasking/window'
json = {
    'type': 'PAYLOAD_IPI',
    'satellite_id': 'FM123',
    'start': 1599445000,
    'duration': 600,
    'parameters': {
        'downlink_budget': 0,
        'copy_from': [
            {
                'src_payload': 'SABERTOOTH',
                'src_path': '/persist/data/locations1',
                'dst_path': '/persist/data/locations1'
            }
        ],
        'adcs_config': {
            'mode': 'TRACKING',
            'aperture': 'IMAGER_TBD',
            'target_latitude_north': 5.240337,
            'target_longitude_east': -52.768472
        },
        'user_command': {
            'executable': '/persist/bin/capture',
            'executable_arguments': [
                '--duration', '60',
                '--interval', '10,
                '--output-dir-for-download', '/outbox/images/'
            ]
        }
    }
}
requests.post(api, headers=auth, json=json)

This window allows the user to run an executable on the imaging payload interface (IPI) which provides access to imaging/camera hardware. The user's executable can make use of software interfaces to trigger the capture of images on the IPI.

The window consists of two phases:

  1. A file copy phase during which files needed from other payloads can be copied to the payload.
  2. A processing phase where a customer-supplied executable is run with customer supplied arguments.
  3. A data retrieval phase where any files written to /outbox are queued for download.

Type

PAYLOAD_IPI

parameters

Name Type Required Description
adcs_config adcs_config no See adcs_config default: { "mode": "NOOP" })
downlink_budget number no kilobytes of data to schedule for download
copy_from list of copy_from no See copy_from (default: [])
user_command user_command yes See user_command

PAYLOAD_SDR

curl -X POST "${HOST}/tasking/window" \
-H "${AUTH_HEADER}" \
-H "Content-Type: application/json" \
-d @- << EOF
{
    "type": "PAYLOAD_SDR",
    "satellite_id": "FM123",
    "start": 1599445000,
    "duration": 600,
    "parameters": {
        "downlink_budget": 0,
        "copy_from": [
            {
                "src_payload": "SABERTOOTH",
                "src_path": "/persist/data/waveform1",
                "dst_path": "/persist/data/waveform1"
            }
        ],
        "adcs_config": {
            "mode": "TRACKING",
            "aperture": "SBAND_SDR",
            "target_latitude_north": 5.240337,
            "target_longitude_east": -52.768472
        },
        "user_command": {
            "executable": "/persist/bin/phase1",
            "executable_arguments": [
                "--input", "/persist/data/waveform1",
                "--output", "/output/results.txt"
            ]
        }
    }
}
EOF
api = host + '/tasking/window'
json = {
    'type': 'PAYLOAD_SDR',
    'satellite_id': 'FM123',
    'start': 1599445000,
    'duration': 600,
    'parameters': {
        'downlink_budget': 0,
        'copy_from': [
            {
                'src_payload': 'SABERTOOTH',
                'src_path': '/persist/data/waveform1',
                'dst_path': '/persist/data/waveform1'
            }
        ],
        'adcs_config': {
            'mode': 'TRACKING',
            'aperture': 'SBAND_SDR',
            'target_latitude_north': 5.240337,
            'target_longitude_east': -52.768472
        },
        'user_command': {
            'executable': '/persist/bin/phase1',
            'executable_arguments': [
                '--input', '/persist/data/waveform1',
                '--output', '/output/results.txt'
            ]
        }
    }
}
requests.post(api, headers=auth, json=json)

This is an updated version of the PAYLOAD_SDR window (the old version is no longer supported). It allows the user to run an executable on the software defined radio (SDR) payload. The supplied executable can make use of software interfaces to send or receive signals with the SDR payload. The previous version of the window included a capture_config, which has been replaced with the following applications, which can be used in a user_command, either invoked directly or included in a script etc. Further documentation can be found here.

  1. RFCollect
  2. RFTransmit
  3. IQGenerator

The window consists of three phases:

  1. A file copy phase during which files needed from other payloads can be copied to the payload. (Noted earlier as "pre-buffer.")
  2. A processing phase where a customer-supplied executable is run with customer supplied arguments.
  3. A data retrieval phase where any files written to /outbox are queued for download. (Noted earlier as "post-buffer.")

IQ Capture Size Limitations

Captured IQ files in uncompressed form must not exceed 1GB in size due to payload memory constraints.

To calculate the uncompressed file size for a capture, a useful upper bound (in kB) can be found by solving 4 * sample_rate_khz * capture_duration rounded up to the nearest 16kB.

Note: The compressed file will likely be much smaller though actual compression ratios depend on signal parameters and will need to be determined experimentally.

Type

PAYLOAD_SDR

parameters

Name Type Required Description
adcs_config adcs_config no See adcs_config default: { "mode": "NOOP" })
downlink_budget number no kilobytes of data to schedule for download
copy_from list of copy_from no See copy_from (default: [])
user_command user_command yes See user_command

Compute Boards

curl -X POST "${HOST}/tasking/window" \
-H "${AUTH_HEADER}" \
-H "Content-Type: application/json" \
-d @- << EOF
{
    "type": "PAYLOAD_SABERTOOTH",
    "satellite_id": "FM123",
    "start": 1599445000,
    "duration": 600,
    "parameters": {
        "downlink_budget": 0,
        "copy_from": [
            {
                "src_payload": "SDR",
                "src_path": "/persist/data/phase1",
                "dst_path": "/persist/data/phase1"
            }
        ],
        "user_command": {
            "executable": "/persist/bin/phase2",
            "executable_arguments": [
                "--input", "/persist/data/phase1",
                "--save-waveform", "/persist/data/waveform1",
                "--output-for-download", "/outbox/phase2.out"
            ]
        }
    }
}
EOF
api = host + '/tasking/window'
json = {
    'type': 'PAYLOAD_SABERTOOTH',
    'satellite_id': 'FM123',
    'start': 1599445000,
    'duration': 600,
    'parameters': {
        'downlink_budget': 0,
        'copy_from': [
            {
                'src_payload': 'SDR',
                'src_path': '/persist/data/phase1',
                'dst_path': '/persist/data/phase1'
            }
        ],
        'user_command': {
            'executable': '/persist/bin/phase2',
            'executable_arguments': [
                '--input', '/persist/data/phase1',
                '--save-waveform', '/persist/data/waveform1',
                '--output-for-download', '/outbox/phase2.out'
            ]
        }
    }
}
requests.post(api, headers=auth, json=json)

A PAYLOAD_SABERTOOTH, PAYLOAD_MARSUPIAL, PAYLOAD_CORAL, PAYLOAD_NANO or PAYLOAD_MYRIAD window consists of three phases:

  1. A file copy phase during which files needed from other payloads, if any, are copied to the compute board.
  2. A processing phase where a customer-supplied executable is run with customer supplied arguments
  3. A data retrieval phase where any files written to /outbox are queued for download

A common use of phase 1 is to retrieve raw or partially processed IQ files from a previous PAYLOAD_SDR window for further processing. See code example in sidebar.

Type

parameters

Name Type Required Description
downlink_budget number no kilobytes of data to schedule for download
copy_from list of copy_from no See copy_from (default: [])
user_command user_command yes See user_command

MAINTENANCE for Brain-in-Space Compute Boards

curl -X POST "${HOST}/tasking/window" \
-H "${AUTH_HEADER}" \
-H "Content-Type: application/json" \
-d @- << EOF
{
    "type": "MAINTENANCE",
    "satellite_id": "FM123",
    "start": 1599445000,
    "duration": 600,
    "parameters": {
        "subsystems": ["SABERTOOTH", "MYRIAD"],
    }
}
EOF
api = host + '/tasking/window'
json = {
    'type': 'MAINTENANCE',
    'satellite_id': 'FM123',
    'start': 1599445000,
    'duration': 600,
    'parameters': {
        'subsystems': ['SABERTOOTH', 'MYRIAD'],
    }
}
requests.post(api, headers=auth, json=json)

The MAINTENANCE window is currently only allowed for ground-side testbeds. It will power up the specified payload(s), as well as ethernet, for access into that payload. Nothing will be executed for the payload. Near the end of the window, the payload(s) will be shutdown.

Only those payloads that are granted access to the user can be powered on for maintenance.

Note: Ground-side testbeds will have a different naming format to the satellite_id than FM123. This information will be provided to you at introduction.

parameters

Name Type Required Description
subsystems list yes a list of payloads to power on during for access. Choose from "SABERTOOTH", "MARSUPIAL", "CORAL", "NANO", "MYRIAD"

Schemas

parameters

The parameters field is a dictionary containing payload window type-specific tuning options. Each payload window type has different parameter sets. See links below.

Windows are configured via the parameters field. Different payload window types take different parameters.

Window Type parameters
Compute boards parameters
LEASE_ADCS parameters
LEASE_ISL parameters
PAYLOAD_DEXTER parameters
PAYLOAD_IPI parameters
PAYLOAD_SDR parameters

user_command

Name Type Required Description
executable string yes path to executable to run
executable_arguments list of strings yes arguments to pass to executable

adcs_config

The ADCS can operate in six modes "AUTONOMOUS", "NADIR", "TRACKING", "LINESCAN", "FIXED_PITCH" or "NOOP".

If no "adcs_config" field is specified, the same behaviour as configuring "NOOP" mode should be expected.

Name Type Required
mode string yes
target_latitude_north number if mode == "TRACKING"
target_longitude_east number if mode == "TRACKING"
aperture string if mode other than "NOOP" or "AUTONOMOUS"
yaw_deg number optional, if mode == "NADIR"
pitch_deg number optional, if mode == "NADIR"
roll_deg number optional, if mode == "NADIR"

Valid modes are: "AUTONOMOUS", "NADIR", "TRACKING", "LINESCAN", or "FIXED_PITCH", "NOOP". Some valid apertures are: "VHF", "UHF", "ADSB", "GNSS", "SBAND_DEXTER", and "SBAND_SDR"

copy_from

The data needed to complete a window may exist on a different payload, commonly as the output of a previous command. To instruct the satellite controller to retrieve this data before executing the user command, these dependencies are listed a sequence of copy operations. Each copy operation indicates the following:

Name Type Required Description
src_payload string yes "IPI", "SDR" or "SABERTOOTH"
src_path string yes path
dst_path string yes path