NAV
Python Javascript

Introduction

Example usage and code samples will appear on this column. Choose which language you’d like to view from the menu at the top.

Python examples assume requests is installed. Javascript assumes the use of jQuery

Welcome to the LCO Developer documentation!

Here you will find API documentation, sample code, tutorials and other resources to aid your development with LCO services.

A note about code formatting

An ellipses ... acts as a placeholder for additional data that would otherwise take up too much space. These will not appear in actual API requests or responses. For example, an endpoint that returns the data:

{ "target": { "type": "SIDEREAL", "name": "m42", "ra": 83.8220792, "dec": -5.3911111, "proper_motion_ra": 1.67, "proper_motion_dec": -0.3, "parallax": 0.0, "coordinate_system": "ICRS", "equinox": "J2000", "epoch": 2000.0, }, }

May be shortened in the documentation to:

{ "target": { ... "type": "SIDEREAL", "name": "m42", ... } }

Information relevant to the documentation being described will always be shown.

Deprecation Policy

LCO wants to make sure we provide a consistent, performant interface to our network services.

When a public API must undergo a breaking change, we will make our best effort to notify all consumers.

When applicable, APIs will be versioned to provide ample time for clients to adapt. Old versions will stay supported for at least 3 months and can be accessed using a different URL. Example:

https://observe.lco.global/api/v2/

LCO will provide documentation at developers.lco.global in order to make API transitions as easy as possible.

Observations

Api root: https://observe.lco.global/api

Overview

The observations API provides endpoints for submitting and querying observation requests.

A UserRequest is a named group of individual observation requests.

A Request is a single unit of observation.

For example: You may submit a UserRequest with a group_id of “Color m51” that is comprised of 3 Requests, each with different filters.

One a UserRequest is submitted, it cannot be changed (however, it can be canceled). You may follow the status of the request using the query endpoints outlined below.

Data Format Definition

UserRequest

The top level entity in the LCO request language is the UserRequest. A user request is a container for Requests that will be described in the next section. It’s main purpose is to provide a top level entity that binds all sub requests together.

A sample UserRequest returned via API:

{
    "id": 12345,
    "submitter": "austin_riba",
    "group_id": "Test observation",
    "observation_type": "NORMAL",
    "operator": "SINGLE",
    "ipp_value": 1.05,
    "created": "2017-03-21T18:53:06.751369Z",
    "state": "PENDING",
    "modified": "2017-03-21T18:53:06.751417Z",
    "proposal": "LCOEngineering"
}
Field Read Only Required Description
id true false The id of this UserRequest.
requests false true The list of Requests to be observed for this User Request
submitter true false The user that submitted the UserRequest.
proposal false true The Proposal under which this observation will be made.
group_id false true A string placed in the FITS header GROUPID for all FITS frames originating from this UserRequest.
observation_type true false The type of observation, NORMAL or TOO.
operator false true The value describes the relationship between the Requests contained in the Request list (SINGLE, MANY).
ipp_value false true A multiplier to your proposals base priority value for this user request and all its children requests. A value > 1.0 will raise your priority and debit your Proposal’s ipp_time_available. A value < 1.0 will lower your priority and credit your Proposal’s ipp_time_available up to your ipp_limit on request success.
state true false The current state of this UserRequest.
created true false The time which this UserRequest was created.
modified true false The time which this UserRequest was changed.

Request

A sample Request returned via API:

{
    "id": 4,
    "location": {},
    "constraints": {},
    "target": {},
    "molecules": [],
    "windows": [],
    "observation_note": "",
    "state": "PENDING",
    "modified": "2017-03-21T18:36:19.456710Z",
    "created": "2017-03-21T18:36:19.456761Z",
}

Requests are the language constructs used to describe an observation of a single target. A request has a Target, Location, list of Molecules, list of Windows describing when the observation can be made, and Constraints that limit the conditions under which the observation should be made.

Field Read Only Required Description
id true false The id of this Request.
location false true The Location where this Request should be observed.
constraints false true The observation Constraints placed on this Request.
target false true The target to observe.
molecules false true A list of instrument configurations.
windows false true A list of time spans in which this request should be considered for observation.
observation_note false false Text describing this request.
state true false The current state of this request.
modified true false The last time this request was modified in any way.
created true false The time when this request was created.

A sample Location returned via API:

{
    "telescope_class": "2m0"
}

Location

A Location specifies on which telescope class will be used for this observation.

Field Read Only Required Description
telescope_class false true The telescope class (1m0, 2m0, 0m4) which will be used for this observation.

Constraints

A sample Constraints returned via API:

{
    "max_airmass": 2.0,
    "min_lunar_distance": 30.0,
}

A Constraints defines the conditions that must be met in order for the request to be considered for scheduling.

Field Read Only Required Description
max_airmass false false Airmass = 1 at zenith.
min_lunar_distance false false Minimum acceptable angular separation between the target and the moon.

Target

Target objects describe what will be observed during an observing request. Targets can be sidereal or non sidereal. Sidereal targets are specified using right ascension and declination. Non sidereal targets are specified using orbital elements.

Field Read Only Required Description
type false true Whether this is a sidereal or non-sidereal target.
name false true The name of this target.
rot_mode false false How the slit is positioned on sky (spectrograph only)
rot_angle false false The angle of the slit if the rotator is set to SKY (spectrograph only)

A sample sideral Target returned via API:

{
    "type": "SIDEREAL",
    "name": "m42",
    "ra": 83.8220792,
    "dec": -5.3911111,
    "proper_motion_ra": 1.67,
    "proper_motion_dec": -0.3,
    "parallax": 0.0,
    "coordinate_system": "ICRS",
    "equinox": "J2000",
    "epoch": 2000.0,
    "acquire_mode": "OPTIONAL",
    "rot_mode": "VFLOAT",
    "rot_angle": 0.0
}

Sidereal Targets

Sidereal targets are used to observe targets that appear to move at or near the sidereal rate.

Field Read Only Required Description
ra false true In decimal degrees.
dec false true In decimal degrees.
proper_motion_ra true false RA proper motion ±33 mas/year.
proper_motion_dec true false Dec proper motion ±33 mas/year.
parallax false false ±0.45 mas.
coordinate_system false true The coordinate system to used. Defaults to ICRS.
equinox false true defaults to 2000.0.

Non Sidereal Targets

Non sidereal targets are used to observe objects that can be described using various orbital element schemes. Two orbital element schemes are available: MPC_MINOR_PLANET and MPC_COMET

A sample non sidereal target returned via api:

{
    "name": "Doomsday Asteroid",
    "type": "NON_SIDEREAL",
    "epoch": 2000,
    "scheme": "MPC_MINOR_PLANET",
    "orbinc": 0,
    "longascnode": 0,
    "argofperih": 0,
    "meandist": 0,
    "eccentricity": 0,
    "meananom": 0
}

MPC_MINOR_PLANET

Field Read Only Required Description
scheme false true The target scheme to use. Can be MPC_MINOR_PLANET or MPC_COMET.
epoch false false Modified Julian days.
orbinc false true Orbital inclination.
longascnode false true Longitude of ascending node (angle in degrees)
argofperih false true Argument of perihelion (angle in degrees)
meandist false true Mean distance (au)
eccentricity false true Eccentricity range from 0 to 0.99
meananom false true Mean anomoly (angle in degrees)

MPC_COMET

Field Read Only Required Description
scheme false true The target scheme to use. Can be MPC_MINOR_PLANET or MPC_COMET.
epoch false false Modified Julian days.
orbinc false true Orbital inclination.
longascnode false true Longitude of ascending node (angle in degrees)
epochofel false true Argument of perihelion (angle in degrees)
longascnode false true Longitude of ascending node (angle in degrees)
meandist false true Mean distance (au)
eccentricity false true Eccentricity range from 0 to 0.99
perihdist false true Mean anomoly (angle in degrees)

Molecule

A sample molecule returned via API:

{
    "type": "EXPOSE",
    "instrument_name": "2M0-SCICAM-SPECTRAL",
    "filter": "v",
    "exposure_time": 30.0,
    "exposure_count": 1,
    "bin_x": 2,
    "bin_y": 2,
    "defocus": 0.0,
    "ag_mode": "OPTIONAL",
    "acquire_mode": "OFF",
    "acquire_radius_arcsec": 0.0,
}

A Molecule represents the configuration of the instrument.

Field Read Only Required Description
type false true The type of exposure (EXPOSE, SPECTRUM, LAMP_FLAT, ARC)
instrument_name false true The type of instrument (1M0-SCICAM-SINISTRO, 2M0-SCICAM-SPECTRAL, 0M4-SCICAM-SBIG, 2M0-FLOYDS-SCICAM)
filter false true The filter (or slit) to use.
exposure_time false true In seconds.
exposure_count false true The number of exposures to take.
bin_x false false Binning in the x dimension.
bin_y false false Binning in the y dimension.
defocus false false Offset of the secondary mirror in mm. Limits are ±3mm.
ag_mode false false Guiding. (OPTIONAL, ON, OFF)
acquire_mode false false WCS or Brightest
acquire_radius_arcsec false false Arc seconds, if acquire_mode is Brightest

Window

A sample window returned via API:

{
    "start": "2017-3-22 14:26:08",
    "end": "2017-3-22 14:26:08"
}

A Window defines the timespan in which the request must be observed.

Field Read Only Required Description
start false true The time when the observing window opens (UT).
end false true The time when the observing window ends (UT).

Migration from V1

The release of the new observing portal and API (codename “Valhalla”) brings with it some backwards incompatible API changes. Those changes are listed here.

Authorization token is required

The API will no longer accept username/password as authentication credentials. All requests (besides the api-token-auth endpoint) must use the Authorization header. Read more about authentication here.

This also means the proposal data structure that was present in the V1 API is now deprecated.

POST requests must use JSON payloads

The new API expects form data to be sent as JSON with a content type of application/json. Previously in V1 the API accepted a form encoded JSON string. If you are using requests this just means using json=<data> instead of data=<data> when sending your POST dictionary.

Data format definition changes

The main difference between the V1 and current API is the removal of Compound Requests data structure. It has been possible to submit observations without Compound Requests for a long time, so if you don’t know what a Compount Request is you can ignore this completely.

New Required fields

The following fields are now required:

In a UserRequest:

  1. group_id
  2. ipp_value
  3. observation_type

In a Target:

  1. type

You can read more about these fields in the Data format definition.

Authentication

requests.post(
    'https://observe.lco.global/api/api-token-auth/',
    data = {
        'username': 'bilbo@lco.global',
        'password': 'myprecious'
    }
).json()
$.ajax({
    url: 'https://observe.lco.global/api/api-token-auth/',
    type: 'post',
    data: {username: 'bilbo', password: 'myprecious'},
    dataType: 'json',
    success: function(data){
        console.log(data.token)
    }
});

Returns the response:

{ "token": "3d46d6b98edef947402e032e73eca7b54661c666" }

The returned token must be set in the Authorization header for all api requests.

requests.get('https://observe.lco.global/api', headers={'Authorization': 'Token <token>'})
$.ajax({
    url: 'https://observe.lco.global/api',
    headers: {'Authorization': 'Token <token>'}
})

All authenticated endpoints require the use of an api token. Once a token is obtained, it must be sent in the Authorization header for each API request:

Authorization: Token <token>

This header must be set for each api request. See the opposite panel for examples on how this may be accomplished.

You may obtain your api token on your profile page.

You may also obtain a token using the api-token-auth endpoint:

Http Request

POST https://observe.lco.global/api/api-token-auth/

Query Parameters

Parameter Required Default Description
username true account username
password true account password

Submit UserRequest

requests.post(
    'https://observe.lco.global/api/userrequests/',
     json={
        'group_id': 'Submit me',
        'proposal': 'Test Proposal',
        'ipp_value': 1.05,
        'operator': 'SINGLE',
        'observation_type': 'NORMAL',
        'requests': [...]
    }
)
$.ajax({
    url: 'https://observe.lco.global/api/userrequests/',
    type: 'post',
    data: {
        'group_id': 'Submit me',
        'proposal': 'Test Proposal',
        'ipp_value': 1.05,
        'operator': 'SINGLE',
        'observation_type': 'NORMAL',
        'requests': [...]
    },
    dataType: 'json',
    success: function(data){
      console.log(data);
    }
});

Returns the response:

{
    "id": 12345,
    "group_id": "Submit me",
    "proposal": "Test Proposal",
    "ipp_value": 1.05,
    "operator": "SINGLE",
    "observation_type": "NORMAL",
    "state": "PENDING",
    "requests": [...]
}

Authentication Required

Submit a UserRequest to be observed.

Http Request

POST https://observe.lco.global/api/userrequests/

Query Parameters

Parameter Required Default Description
* true A well formed userrequest in JSON format.

Get All UserRequests

Authentication Required

Returns a list of UserRequests that have been submitted under proposals that you are a member of.

requests.get('https://observe.lco.global/api/userrequests/?state=PENDING&user=austin_riba').json()
$.getJSON('https://observe.lco.global/api/userrequests/?state=PENDING&user=austin_riba')

Returns the response:

{
    "count": 18,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": 4,
            "requests": [...],
            "submitter": "austin_riba",
            "group_id": "testhis",
            "observation_type": "NORMAL",
            "operator": "SINGLE",
            "ipp_value": 1.05,
            "created": "2017-03-21T18:36:19.454879Z",
            "state": "PENDING",
            "modified": "2017-03-21T18:36:19.454930Z",
            "proposal": "LCOEngineering"
        }
    ]
}

Http Request

GET https://observe.lco.global/api/userrequests/

Query Parameters

Parameter Required Default Description
created_after false Result includes requests created after given date.
created_before false Result includes requests created before given date.
state false Result includes requests matching state (PENDING, SCHEDULED, CANCELED, COMPLETED, WINDOW_EXPIRED).
title false Result includes requests with a group_id that contains or matches given value.
user false Result includes requests submitted by users who’s username contains given value.
proposal false Result includes requests submitted under specified proposal.
observation_type false Results include specified observation type (NORMAL, TARGET_OF_OPPORTUNITY)
ipp_value false Results include UserRequests with the specidied IPP Value
ordering false -id Order results by a specific field ie modified. Use - for descending order.

Get Single UserRequest

Authentication Required

Returns a single instance of a UserRequest.

requests.get('https://observe.lco.global/api/userrequests/3456/').json()
$.getJSON('https://observe.lco.global/api/userrequests/3456/')

Returns the response:

{
    "id": 3456,
    "requests": [...],
    "submitter": "austin_riba",
    "group_id": "testhis",
    "observation_type": "NORMAL",
    "operator": "SINGLE",
    "ipp_value": 1.05,
    "created": "2017-03-21T18:36:19.454879Z",
    "state": "PENDING",
    "modified": "2017-03-21T18:36:19.454930Z",
    "proposal": "LCOEngineering"
}

Http Request

GET https://observe.lco.global/api/userrequests/<id>/

Query Parameters

Parameter Required Default Description
id true The id of the UserRequest

Cancel UserRequest

Authentication Required

UserRequests can not be deleted however they can be canceled. Once canceled, a UserRequest will no longer be considered for scheduling.

requests.put('https://observe.lco.global/api/userrequests/3456/cancel/').json()
$.ajax({
    url: 'https://observe.lco.global/api/userrequests/3456/cancel/',
    type: 'put',
    success: function(data){
        console.log(data)
    }
});

Returns the response:

{
    "id": 3456
    ...
    "state": "CANCELED"
}

Http Request

PUT https://observe.lco.global/api/userrequests/<id>/cancel/

Query Parameters

Parameter Required Default Description
id true The id of the UserRequest

Validate a UserRequest

requests.post(
    'https://observe.lco.global/api/userrequests/validate/',
    json={
        'group_id': 'Validate me',
        'proposal': 'Test Proposal',
        'requests': [...]
    }
).json()
$.ajax({
    url: 'https://observe.lco.global/api/userrequests/validate/',
    type: 'post',
    data: {
        "group_id": "Validate me",
        "proposal": "Test Proposal",
        "requests": [...]
    },
    dataType: 'json',
    success: function(data){
      console.log(data);
    }
});

Returns the response:

{
    "request_durations": {},
    "errors": {
        "requests":{ ... }
}

Authentication Required

This endpoint is used to check if a UserRequest is valid before submission. It also contains the duration of the request that will be debited if submitted.

Http Request

POST https://observe.lco.global/api/userrequests/validate/

Query Parameters

Parameter Required Default Description
* true A well formed UserRequest in JSON format

Get Max Allowable IPP

requests.post(
    'https://observe.lco.global/api/userrequests/max_allowable_ipp/',
    json={
        "group_id": "Check Ipp",
        "proposal": "Test Proposal",
        "requests": [...]
    }
).json()
$.ajax({
    url: 'https://observe.lco.global/api/userrequests/max_allowable_ipp/',
    type: 'post',
    data: {
        "group_id": "Check Ipp",
        "proposal": "Test Proposal",
        "requests": [...]
    },
    dataType: 'json',
    success: function(data){
      console.log(data);
    }
});

Returns the result:

{
    "2016B": {
        "1m0": {
            "ipp_time_available": 1.0,
            "ipp_limit": 10.0,
            "request_duration": 1.54,
            "max_allowable_ipp_value": 1.649,
            "min_allowable_ipp_value": 0.5
        }
    }
}

Authentication Required

Given a well formed UserRequest returns miscellaneous information pertaining to IPP per semester/telescope class.

HTTP Request

POST https://observe.lco.global/api/userrequests/max_allowable_ipp/

Query Parameters

Parameter Required Default Description
* true A well formed UserRequest in JSON format

Generate Cadence

requests.post(
    'https://observe.lco.global/api/userrequests/cadence/',
    json={
        'group_id': 'generate cadence',
        'proposal': 'Test Proposal',
        'requests': [{
            'cadence': {
                'start': '2016-09-01T21:12:18Z',
                'end': '2016-09-03T22:12:19Z',
                'period': 24.0,
                'jitter': 12.0
            },
            ...
        }]
    }
).json()
$.ajax({
    url: 'https://observe.lco.global/api/userrequests/cadence/',
    type: 'post',
    data: {
        "group_id": "generate cadence",
        "proposal": "Test Proposal",
        "requests": [{
            "cadence": {
                "start": "2016-09-01T21:12:18Z",
                "end": "2016-09-03T22:12:19Z",
                "period": 24.0,
                "jitter": 12.0
            },
            ...
        }]
    },
    dataType: 'json',
    success: function(data){
      console.log(data);
    }
});

Returns the response:

{
    "id": 3456
    ...
    "requests":[{
        "windows":[{
            "start": "2016-09-01T21:12:18Z",
            "end": "2016-09-02T03:12:18Z"
        }],
        ...
        },{
        "windows":[{
            "start": "2016-09-02T15:12:18Z",
            "end": "2016-09-03T03:12:18Z"
        }],
        ...
    }]
}

Authentication Required

Given a well formed UserRequest containing a single Request that has a cadence key, this endpoint returns a new UserRequest with multiple requests generated by the cadence function.

HTTP Request

POST https://observe.lco.global/api/userrequests/cadence/

Query Parameters

Parameter Required Default Description
* true A well formed UserRequest in JSON format
start true The UTC date that marks the beginning of the cadence
end true The UTC date that marks the ending of the cadence
period true The fractional hours between observations in your cadence. A 24 hour window with a period of 6 hours should have 3-4 requests created within it (if they are all visible)
jitter true The fractional hours +/- to make each cadence request window. A 24 hour window with a period of 6.0 hours and jitter of 1.5 hours will create a requests with windows centered every 6 hours, with their start and end times +/- 1.5 hours from those centers.

Airmass

requests.get('https://observe.lco.global/api/requests/12345/airmass/').json()
$.getJSON('https://observe.lco.global/api/requests/12345/airmass/')

Returns the response:

{
    "airmass_data": {
        "cpt": {
            "times": [
                "2017-03-10T00:00",
                "2017-03-10T00:10",
                "2017-03-10T00:20",
            ],
            "airmasses": [
                1.1742551260332688,
                1.1956410351734084,
                1.2190628569952935,
            ]
        },
        "lsc": {
            "times": [
                "2017-03-10T00:00",
                "2017-03-10T00:10",
                "2017-03-10T00:20",
            ],
            "airmasses": [
                1.4136946116338753,
                1.374117740986236,
                1.3379014027310017,
            ]
        }
    },
    "airmass_limit": 2.0
}

Authentication Required

For a specific request, return the airmasses at visible sites at 10 minute intervals. Only sites at which the target is visible above the airmass_limit provided will be returned.

HTTP Request

GET https://observe.lco.global/api/requests/<id>/airmass/

Query Parameters

Parameter Required Default Description
id true The id of the request

Proposals

Api root: https://observe.lco.global/api/proposals

This api provides endpoints for retrieving time used/allocated, PIs, CoIs, and other information pertaining to proposals.

Proposal Definition

A sample Proposal returned via API:

    {
        "id": "LCOTest-001",
        "timeallocation_set": [
            {
                "std_allocation": 25.0,
                "std_time_used": 14.3253,
                "ipp_limit": 0.0,
                "ipp_time_available": 0.0,
                "too_allocation": 0.0,
                "too_time_used": 0.0,
                "telescope_class": "1m0",
                "semester": "2017AB",
                "proposal": "LCOTest-001"
            }
        ],
        "users": [
            "isaac_newton",
            "ggalileo@lco.global"
        ],
        "pi": "isaac_newton",
        "active": false,
        "title": "Study fun things",
        "abstract": "This work is to ...",
        "tac_priority": 1000,
        "tac_rank": 0,
        "public": false,
        "tag": "LCO"
    }
Field Description
id The id of this Proposal.
timeallocation_set The set of timeallocation objects associated with this Proposal.
users The set of users (co-investigators) associated with this Proposal.
pi The pi for this Proposal.
active Boolean field of whether requests can still be submitted with this Proposal.
title The title of the Proposal.
abstract The abstract of the Proposal.
tac_priority The priority of the Proposal as awarded by the TAC.
tac_rank The numerical ranking given to the Proposal by the TAC.
tag The group this Proposal is a part of.

Authentication

Authentication for the proposals API is exactly the same as the Observations API.

Get all Proposals

requests.get('https://observe.lco.global/api/proposals/')
$.getJSON('https://observe.lco.global/api/proposals/')

Returns the response:

{
    "count": 2,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": "LCOEPO1",
            "timeallocation_set": [
                {
                    "std_allocation": 15.0,
                    "std_time_used": 4.754,
                    "ipp_limit": 1.5,
                    "ipp_time_available": 0.75,
                    "too_allocation": 0.0,
                    "too_time_used": 0.0,
                    "telescope_class": "1m0",
                    "semester": "2016A",
                    "proposal": "WhiteFuzzies"
                },
            ],
            "users": [
                "bilbo@baggins.com",
                "darth.vader@empire.uk",
                "mario@plumbers.com"
            ],
            "pi": "darth.vader@empire.uk",
            "active": true,
            "title": "Observations of Stuff in the Sky",
            "abstract": "We want pretty pictures",
            "tac_priority": 1,
            "tac_rank": 1,
            "public": false,
            "tag": "LCO"
        },
        {
            "id": "LCOEPO2",
            "timeallocation_set": [
                {
                    "std_allocation": 63.0,
                    "std_time_used": 21.0,
                    "ipp_limit": 0.0,
                    "ipp_time_available": 0.0,
                    "too_allocation": 2.0,
                    "too_time_used": 0.0,
                    "telescope_class": "1m0",
                    "semester": "2014B",
                    "proposal": "LCOEPO2"
                }
            ],
            "users": [
                "steve.pete@downhill.eu",
                "aaron.gwin@fast.com"
            ],
            "pi": "aaron.gwin@fast.com",
            "active": false,
            "title": "Observing Mars",
            "abstract": "Mars observations",
            "tac_priority": 2,
            "tac_rank": 2,
            "public": false,
            "tag": "LCO"
        },
    ]
}

Authentication Required

Returns a list of proposals that belong to the authenticated user. A TimeAllocation represents the observing time in hours granted to a proposal for a single semester and telescope class.

HTTP Request

GET https://observe.lco.global/api/proposals/

Query Parameters

See Proposal Definition for parameters

Get Single Proposal

requests.get('https://observe.lco.global/api/proposals/LCOEPO1/')
$.getJSON('https://observe.lco.global/api/proposals/LCOEPO1/')

Returns the response:

 {
    "id": "LCOEPO1",
    "timeallocation_set": [
        {
            "std_allocation": 15.0,
            "std_time_used": 4.754,
            "ipp_limit": 1.5,
            "ipp_time_available": 0.75,
            "too_allocation": 0.0,
            "too_time_used": 0.0,
            "telescope_class": "1m0",
            "semester": "2016A",
            "proposal": "WhiteFuzzies"
        },
    ],
    "users": [
        "bilbo@baggins.com",
        "darth.vader@empire.uk",
        "mario@plumbers.com"
    ],
    "pi": "darth.vader@empire.uk",
    "active": true,
    "title": "Observations of Stuff in the Sky",
    "abstract": "We want pretty pictures",
    "tac_priority": 1,
    "tac_rank": 1,
    "public": false,
    "tag": "LCO"
}

Authentication Required

Return information about a single proposal.

HTTP Request

GET https://observe.lco.global/api/proposals/<id>/

Query Parameters

Parameter Required Default Description
id true The id of the proposal

Semesters

Time at LCO is organized into Semesters. However not all semesters are of uniform length. This api provides a convienent way to see when semesters start and end.

API root: https://observe.lco.global/api/semesters/

Get All Semesters

requests.get('https://observe.lco.global/api/semesters/').json()
$.getJSON('https://observe.lco.global/api/semesters/')

Returns the response:

{
    "count": 9,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": "2016B",
            "start": "2016-10-01T00:00:00Z",
            "end": "2017-03-31T23:59:59Z"
        },
        {
            "id": "2016A",
            "start": "2016-04-01T00:00:00Z",
            "end": "2016-09-30T23:59:59Z"
        },
        ...
    ]
}

Requesting the semester that contains the date 4-10-2017:

requests.get('https://observe.lco.global/api/semesters/?semester_contains=2017-04-10').json()
$.getJSON('https://observe.lco.global/api/semesters/?semester_contains=2017-04-10')

Returns the response:

{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": "2017AB",
            "start": "2017-04-01T00:00:00Z",
            "end": "2017-11-30T23:59:59Z"
        }
    ]
}

Returns a list of all Semesters.

HTTP Request

GET https://observe.lco.global/api/semesters/

Query Parameters

Parameter Required Default Description
id false The id of the Semester
semester_contains false Result is the Semester that contains the date (should only be one).
start false The start date of the Semester
end false The end date of the Semester

Get Single Semester

requests.get('https://observe.lco.global/api/semesters/2016B/')
$.getJSON('https://observe.lco.global/api/semesters/2016B/')

Returns the response:

{
    "id": "2016B",
    "start": "2016-10-01T00:00:00Z",
    "end": "2017-03-31T23:59:59Z"
}

Return a single Semester.

HTTP Request

GET https://observe.lco.global/api/semesters/<id>/

Query Parameters

Parameter Required Default Description
id true The id of the Semester

Telescope States

Get Telescope States

requests.get('https://observe.lco.global/api/telescope_states/?start=2017-03-23&end=2017-03-24&site=lsc&site=coj&telescope=1m0a').json()
$.getJSON('https://observe.lco.global/api/telescope_states/?start=2017-03-23&end=2017-03-24&site=lsc&site=coj&telescope=1m0a')

Returns the response:

{
     "lsc.domb.1m0a": [
        {
            "telescope": "lsc.domb.1m0a",
            "event_type": "AVAILABLE",
            "event_reason": "Available for scheduling",
            "start": "2017-03-23T00:03:03Z",
            "end": "2017-03-23T01:27:51Z"
        },
        {
            "telescope": "lsc.domb.1m0a",
            "event_type": "SEQUENCER_DISABLED",
            "event_reason": "Sequencer in MANUAL state",
            "start": "2017-03-23T01:27:51Z",
            "end": "2017-03-23T01:36:38Z"
        },
        ...
    ],
    "lsc.domc.1m0a": [
      ...
    ],
    "coj.domb.1m0a": [
      ...
    ],
    ...
}

Returns the state of the LCO network between start and end times.

HTTP Request

GET https://observe.lco.global/api/telescope_states/

Query Parameters

Parameter Required Default Description
start false 24 hours ago Start time (ISO Format)
end false now End time (ISO Format)
site false sites to filter by (site abbreviation)
telescope false telescopes to filter by (1m0a, 2m0a, 0m4a, etc.)

Telescope Availability

Get Telescope Availability

requests.get('https://observe.lco.global/api/telescope_availability/?start=2017-03-23&end=2017-03-24&site=lsc&site=ogg').json()
$.getJSON('https://observe.lco.global/api/telescope_availability/?start=2017-03-23&end=2017-03-24&site=lsc&site=ogg')

Returns the response:

{
    "lsc.domb.1m0a": [
        [
            "2017-03-23",
            1.0
        ]
    ],
    "ogg.clma.0m4b": [
        [
            "2017-03-23",
            1.0
        ]
    ]
}

Returns the percentage of time specific telescope were available over the given time range.

HTTP Request

GET https://observe.lco.global/api/telescope_availability/

Query Parameters

Parameter Required Default Description
start false 24 hours ago Start time (ISO Format)
end false now End time (ISO Format)
site false sites to filter by (site abbreviation)
telescope false telescopes to filter by (1m0a, 2m0a, 0m4a, etc.)

Archive

Api Root: https://archive-api.lco.global

The archive API is a web service which provides a RESTful interface to the data stored in the archive.

To access it, use any library or program which can understand HTTP: for example, a web browser. Visiting https://archive-api.lco.global in your browser will take you to the browseable API. Here you can explore the various endpoints available, craft queries and view the JSON that will be returned. The exact URLs you visit in the browseable API can be used to return JSON to other programs, so it is a useful tool to explore the API.

The API can also be accessed using a variety of programmatic interfaces, such as curl:

curl https://archive-api.lco.global/frames/ > results.json

Which will get the metadata for the last 100 data products in the archive, and store that information in results.json

Authentication

requests.post(
    'https://archive-api.lco.global/api-token-auth/',
    data = {
        'username': 'bilbo@lco.global',
        'password': 'myprecious'
    }
).json()
$.ajax({
    url: 'https://archive-api.lco.global/api-token-auth/',
    type: 'post',
    data: {username: 'bilbo', password: 'myprecious'},
    dataType: 'json',
    success: function(data){
        console.log(data.token)
    }
});

Returns the response:

{ "token": "3d46d6b98edef947402e032e73eca7b54661c666" }

The returned token must be set in the Authorization header for all api requests.

requests.get('https://archive-api.lco.global/frames/', headers={'Authorization': 'Token <token>'})
$.ajax({
    url: 'https://archive-api.lco.global/frames/',
    headers: {'Authorization': 'Token <token>'}
})

The archive API is authenticated and will only return results the user is authorized to view. For a non logged in user, this is all public data. For a logged in user, this is public data and data which belongs to proposals that the user is a part of.

A user can authenticate by posting a username and password to the /api-token-auth/ endpoint which will return an API token. The token must then be placed in the Authorization header of subsequent requests in the the following form:

Token <token>

An example of obtaining a token using curl:

curl --data "username=bilbo@lco.global&password=myprecious" https://archive-api.lco.global/api-token-auth/

returns:

{"token":"3d46d6b98edef947402e032e73eca7b54661c968"}

The token can now be used in resulting requests:

curl --header "Authorization: Token 3d46d6b98edef947402e032e73eca7b54661c968" https://archive-api.lco.global/frames/

Data Format Definition

A sample frame returned via API:

{
    "id": 42120,
    "basename": "ogg2m001-fs02-20160202-0133-e91",
    "area": {
        "type": "Polygon",
        "coordinates": [
            [
                [
                    135.12548613998868,
                    36.53399918890214
                ],
                [
                    135.12571388933247,
                    36.701867589076244
                ],
                [
                    134.91633784602044,
                    36.70186763472167
                ],
                [
                    134.91656548197224,
                    36.53399923426909
                ],
                [
                    135.12548613998868,
                    36.53399918890214
                ]
            ]
        ]
    },
    "related_frames": [
        1375,
        42119,
        42078,
        42040,
        42039
    ],
    "version_set": [
        {
            "id": 44713,
            "created": "2016-02-03T22:27:59.236409Z",
            "key": "dtxW9DM0lwKNpsPYlnhEzDt41OCp7q0i",
            "md5": "e1836a49b573ac50ccddba7e54661564",
            "extension": ".fits",
            "url": "https://lcogtarchivetest.s3.amazonaws.com/44f2/ogg2m001-fs02-20160202-0133-e90?versionId=dtxW9DM0lwKNpsPYlnhEzDt41OCp7q0i&Expires=1454542848&AWSAccessKeyId=AKIAIZBYNSZZGYN3EAQQ&Signature=T3XtzW8bTYqI48haJZFvEMdqb6M%3D"
        }
    ],
    "url": "https://lcogtarchivetest.s3.amazonaws.com/44f2/ogg2m001-fs02-20160202-0133-e90?versionId=dtxW9DM0lwKNpsPYlnhEzDt41OCp7q0i&Expires=1454542848&AWSAccessKeyId=AKIAIZBYNSZZGYN3EAQQ&Signature=T3XtzW8bTYqI48haJZFvEMdqb6M%3D",
    "filename": "ogg2m001-fs02-20160202-0133-e90.fits",
    "RLEVEL": 91,
    "DATE_OBS": "2016-02-03T09:05:57.414000Z",
    "PROPID": "FTPEPO2014A-003",
    "INSTRUME": "fs02",
    "OBJECT": "P 2010 v1",
    "SITEID": "ogg",
    "TELID": "2m0a",
    "EXPTIME": "60.000",
    "FILTER": "R",
    "L1PUBDAT": "2016-02-03T09:05:57Z",
    "OBSTYPE": "EXPOSE",
    "BLKUID": 54321,
    "REQNUM": 12345
}

The archive endpoints return metadata formatted in json. An example of a typical entry corresponding to a single data product is given on the right.

Much of the meta-data matches values from the file’s FITS headers:

Field Description
DATE_OBS The UTC time at the start of exposure.
PROPID The name of the proposal for which this frame was taken.
INSTRUME The instrument that produced this frame.
OBJECT The name of the object given by the user as the target of the observation. Note this is not the same as searching by on sky position - the OBJECT header is free-form text which may or may not match the actual contents of the file.
SITEID The site that produced this frame.
TELID The telescope that produced this frame.
EXPTIME The exposure time of the frame.
FILTER The filter used to produce this frame.
L1PUBDAT The date this frame become public.
OBSTYPE The type of exposure: EXPOSE, BIAS, SPECTRUM, CATALOG, etc.
BLKUID The Block ID of the frame
REQNUM The Request number of the frame
RLEVEL The reduction level of the frame. Currently, there are 3 reduction levels: Some of the meta-data fields are derived and not found in the FITS headers. 0 (Raw), 11 (Quicklook), 91 (Final reduced).
Field Description
basename is the base of the filename without a file extension.
area is a WKT Polygon which represents the frame’s coverage of the sky. Each point in the polygon is a RA Dec pair in degrees.
related_frames is a list of ids of other frames that are related to this one. These can include calibration files, catalog files, final data products, etc.
version_set is a list of versions for this frame. Each version contains a url to download the file, a file extension, an md5 checksum, and a datetime.
url is the URL to download the frame, from the latest version.

Aggregate

requests.get('https://archive-api.lco.global/aggregate/').json()
$.getJSON('https://archive-api.lco.global/aggregate/')

Returns the response:

{
  "filters": [
      "ip",
      "LL",
      "zs",
  ],
  "instruments": [
      "fl04",
      "fs02",
      "en05",
  ],
  "telescopes": [
      "2m0a",
      "1m0a",
      "0m4a",
  ],
  "obstypes": [
      "SKYFLAT",
      "BIAS",
      "EXPOSE",
  ],
  "sites": [
      "ogg",
      "tfn",
      "bpl",
  ]
}

Returns the unique values shared across all fits files for site, telescope, instrument, filter and obstype.

HTTP Request

GET https://archive-api.lco.global/aggregate/

Query Parameters

None

List Frames

requests.get('https://archive-api.lco.global/frames/').json()
$.getJSON('https://archive-api.lco.global/frames/')

Returns the response:

{
  "count": 9000,
  "next": "https://archive-api.lco.global/frames/?limit=100&offset=100",
  "previous": null,
  "results": [
    {
      ... Frame Payload ...
    }
  ]
}

Return a list of frames.

HTTP Request

GET https://archive-api.lco.global/frames/

Query Parameters

All parameters are optional

Parameter Type Description
basename string Frames which contain this value in their basename
DATE OBS datetime Frames taken exactly on this date
PROPID string Frames which belong to this proposal
SITEID string Frames produced at this site
TELID string Frames produced from this telescope
Filter string Frames produced using this filter
OBSTYPE string Frames which match this OBSTYPE
INSTRUME string Frames taken with this instrument
OBJECT string Frames which contain this value in their OBJECT header
start datetime Frames with a DATE-OBS later than this date
end datetime Frames with a DATE-OBS earlier than this date
public boolean Frames that are public. Default: true
RLEVEL integer Frames at this reduction level
L1PUBDAT datetime Frames that go public on this date
covers POINT Frames which cover this specific point.

Note about the POINT datatype: The value is a WKT point of RA and DEC in degrees. Example /frames/?covers=POINT(34.4 -20.9)

Get Single Frame

requests.get('https://archive-api.lco.global/frames/42/').json()
$.getJSON('https://archive-api.lco.global/frames/42/')

Returns the response:

{
    "id": 32,
  ... frame payload ...
}

Returns details about a specific frame.

HTTP Request

GET https://archive-api.lco.global/frames/<id>/

Query Params:

Parameter Type Description
id integer The id of this frame
requests.get('https://archive-api.lco.global/frames/42/related/').json()
$.getJSON('https://archive-api.lco.global/frames/42/related/')

Returns the response:

[
  {
    ... List of frames ...
  }
]

Returns calibration, raw/reduced frames associated with this frame.

HTTP Request

GET https://archive-api.lco.global/frames/<id>/related/

Query Params:

Parameter Type Description
id integer The id of this frame

Get Headers

requests.get('https://archive-api.lco.global/frames/42/headers/').json()
$.getJSON('https://archive-api.lco.global/frames/42/headers/')

Returns the response:

{
    "data": {
        "AZIMUTH": 180.3819459,
        "OBSGEO_Y": -5213920.079,
        "M1COVER": "DEPLOYED",
        "SCHEDSEE": "",
        "FOCOBOFF": 0.0,
        "FILTER1": "air",
        "NAXIS2": 4096,
        ...
    }
}

Retrieve the FITS headers for this frame.

HTTP Request

GET https://archive-api.lco.global/frames/<id>/headers/

Query Params:

Parameter Type Description
id integer The id of this frame

Profile

requests.get('https://archive-api.lco.global/profile/').json()
$.getJSON('https://archive-api.lco.global/profile/')

Returns the response:

{
  "username": "bilbo@lco.global",
  "profile": {
    "proposals": [
      "FellowshipProposal",
      "Hobbits2015A",
      "Quests"
    ]
  }
}

Returns details about the currently authenticated user.

HTTP Request

GET https://archive-api.lco.global/profile/

Query Params:

None

Code Samples

lcogtDD

Nestor Espinoza has written a command line script to download files from the LCO archive.

View on Github

Thumbservice

The Thumbnail API is a flask script which takes advantage of the LCO Archive API.

View on Github

Thumbnails

API Root: https://thumbnails.lco.global

The thumbnail service provides a simple api to generate images from data stored on the archive. This api is useful for creating interfaces or education material.

Authentication

The thumbnail api passes through the value of the Authorization HTTP header through to the archive api. For proprietary data it is necessary to provide this header, public data needs no authentication. Thus, to authenticate with the thumnail api, you must first obtain an authentication key from the archive api. Then make requests to the thumbnail api, using the Authorization header as you would on the archive.

Generate Thumbnail

requests.get('https://thumbnails.lco.global'/<frame_id>/').json()
$.getJSON('https://thumbnails.lco.global/<frame_id>/')

Returns the response:

{

    "propid": "FTPEPO2014A-003",
    "url": "https://s3-us-west-2.amazonaws.com/thumbnails.lcogt.net/6124256.4163566684581698428.jpg?AWSAccessKeyId=AKIAIIXJI2IT23CSF2RA&Expires=1493352936&Signature=x%2B5b8ZHZTW850dVVx%2ByyYiLIGbY%3D"

}

Generates a thumbnail from the frame identified by frame_id. The url to the jpg will be returned in the url key of the response.

To obtain the frame id, use the archive api.

HTTP Request

GET https://thumbnails.lco.global/<frame_id>/

Query Parameters

Parameter Required Description
frame_id true The id of the frame to be thumbnailed
width false The width (in pixels) of the generated image
label false Place text on the thumbnail
color false Generate a color image. note: this only works for frames where there are R,V and B filter versions of the same observation.

Pressure

Get Network Pressure

requests.get('https://observe.lco.global/api/pressure/?site=lsc').json()
$.getJSON('https://observe.lco.global/api/pressure/?site=lsc')

Returns the response:

{
    "pressure_data": [
        {},
        {},
        ...
        {
            "All Proposals": 0.00019054754269455878,
        },
        {
            "All Proposals": 0.00019054754269455878,
        },
        {
            "All Proposals": 0.00019054754269455878,
        },
        {
            "All Proposals": 0.00019054754269455878,
        },
        ...
        {},
        {},
    ],
    "time_bins": [
        "2017-05-19T00:50:14.537278Z",
        "2017-05-19T01:05:14.537278Z"
        ...
        "2017-05-20T00:20:14.537278Z",
        "2017-05-20T00:35:14.537278Z"
    ],
    "site_nights": [
        {
            "name": "lsc",
            "start": 2.691666666666667,
            "stop": 14.288055555555555
        }
    ],
    "site": "lsc",
    "instrument_name": "all",
    "time_calculated": "2017-05-19T00:50:14.537278Z"
}

The pressure of a block is defined as its length divided by the total length of time during which it is visible. For each time bin, this value is further divided by the number of telescopes from which the block is visible during that time bin. An overall pressure of 1 (dashed line) means the network is perfectly subscribed on average (> 1 is over-subscription, < 1 is under-subscription).

The returned data structure has two keys: pressure and site_nights. pressure is an array of 15 minute time buckets (from now + 15min to now + 24 hours) who’s value is the pressure on that bucket.

site_nights shows the start and end times of the site’s local night, in hours from now.

HTTP Request

GET https://observe.lco.global/api/pressure/

Query Parameters

Parameter Required Default Description
site false all Only return pressure for a specific site code.
instrument false all Only show pressure for a specific instrument

Contention

Get Contention

requests.get('https://observe.lco.global/api/contention/1M0-SCICAM-SINISTRO/').json()
$.getJSON('https://observe.lco.global/api/contention/1M0-SCICAM-SINISTRO/')

Returns the response:

{
    "contention_data": [
        {
            "All Proposals": 0
        },
        {
            "All Proposals": 0
        },
        {
            "All Proposals": 584
        },
        ...
        {
            "All Proposals": 0
        },
        {
            "All Proposals": 4360
        },
        {
            "All Proposals": 16890
        },
    ],
    "ra_hours": [
        0,
        1,
        ...
        22,
        23
    ],
    "instrument_name": "1M0-SCICAM-SINISTRO",
    "time_calculated": "2017-05-19T00:50:14.606194Z"
}

This endpoint returns the amount of telescope time requested by RA and instrument. Observations requested where contention is high are more likely to incur scheduling conflicts.

The returned data structure is an array of RA’s and the contention at that RA. The value is in total seconds.

HTTP Request

GET https://observe.lco.global/api/contention//<instrument>/

Query Parameters

Parameter Required Default Description
instrument false all Only show contention for a specific instrument