HATPI Data API
Query HATPI light curves and frames from your terminal, scripts, or notebooks. Every endpoint takes a JSON body and returns JSON, CSV, FITS, or VOTable.
-
1
Get an API key
Free with any HATPI account. Create one on your account page; the key is displayed only once, so store it securely.
-
2
Save it in your terminal
Run this once per terminal session. All examples on this page read the key from this variable.
export HATPI_API_KEY="your-key" -
3
Make a request
Fetch light curves by Gaia DR2 ID, or search frames by sky position.
Authentication
Every request requires your API key. Set it once per terminal session with the export command shown here; all examples on this page read it from the HATPI_API_KEY environment variable.
To make it persistent, add the same line to your shell startup file (~/.zshrc on macOS, ~/.bashrc on most Linux systems). Jupyter and Python processes started from that shell inherit the variable.
The examples send the key in the HTTP header Authorization: Bearer <key>; clients written in other languages must send the same header. Requests without a valid key receive 401 Unauthorized.
export HATPI_API_KEY="your-key"
{
"error": "Authentication required. Send your API key as 'Authorization: Bearer <key>'. Get a free key at https://hatpi.org/auth/account"
}
Data service
Light Curves
/api/lightcurves
Fetch full-resolution light curves for up to 25 stars by Gaia DR2 ID. Each star has one entry per observing season and photometry type. By default every season is returned; use the filters below to narrow the request.
list_only. One star across several seasons can be
tens of megabytes. List the available seasons first, then request only the
season and photometry you need.
Body parameters
gaia_idsarray of stringsrequired-
Gaia DR2 source IDs, up to 25. Pass them as strings: 19-digit numbers
lose precision in many JSON libraries. A single
gaia_idstring is also accepted. list_onlyboolean- If
true, return season metadata without the data columns. Defaultfalse. photometrystring"subtracted"(difference-image photometry) or"aperture"(aperture photometry). Omit for both.seasonstring- Four-digit year a season starts in, e.g.
"2023". Omit for all seasons. selected_flagsarray of integers-
Keep only points whose primary flag (
FLAG0) matches.0keeps unflagged points; any other value keeps points that have that bit set. Omit to return every point. The web viewer defaults to[0, 2, 64].
Query parameters
formatstringjson(default),csv, orfits. CSV has one row per data point, with the star and season repeated on each row. FITS returns a ZIP archive of the stored FITS files, one per season; it is not available withlist_onlyorselected_flags.
Response
JSON responses are {"count", "not_found", "results"}. Each result has a
gaia_id and a list of seasons, each with photometry,
start_date and end_date (YYYYMMDD), and version.
Without list_only, each season also has n_points and columns.
IDs with no light curves are listed in not_found.
Data columns
Returned per season under columns (JSON) or as CSV columns. Suffixes 0–2 are the three photometric apertures.
| Column | Description |
|---|---|
TIME | Time of each measurement |
FITMAG0–2 | Fitted magnitudes |
EPD0–2 | Magnitudes after External Parameter Decorrelation |
TFA0–2 | Magnitudes after the Trend Filtering Algorithm |
ERR0–2 | Magnitude uncertainties |
FLAG0–2 | Quality flags (bitmask, see below) |
HA, Z | Hour angle and zenith distance |
FRAMEKEY | Identifier of the source frame |
LCGROUP | Light-curve group |
Quality flags
Flags are bits and can combine: 80 = 16 + 64.
| Bit | Meaning |
|---|---|
0 | Good photometry, no flag |
1 | Saturated or hot pixels, or off the CCD edge |
2 | Some saturated or hot pixels in the aperture |
4 | Asteroid in the aperture |
8 | Satellite in the aperture |
16 | Bad frame (excessive outliers) |
32 | Excluded from the TFA fit |
64 | Large pointing offset |
{
"count": 1,
"not_found": [],
"results": [
{
"gaia_id": "3648155941461125760",
"seasons": [
{
"end_date": "20230908",
"photometry": "aperture",
"start_date": "20230107",
"version": 1
},
{
"end_date": "20230908",
"photometry": "subtracted",
"start_date": "20230107",
"version": 4
},
…
]
}
]
}
{
"count": 1,
"not_found": [],
"results": [
{
"gaia_id": "3648155941461125760",
"seasons": [
{
"columns": {
"ERR0": [0.0041, 0.0042, …],
"FITMAG0": [12.4031, 12.4057, …],
"FLAG0": [0, 0, …],
"TIME": [ … ],
…
},
"end_date": "20230908",
"n_points": 18342,
"photometry": "subtracted",
"start_date": "20230107",
"version": 4
}
]
}
]
}
gaia_id,photometry,start_date,end_date,version 3648155941461125760,aperture,20230107,20230908,1 3648155941461125760,subtracted,20230107,20230908,4 …
gaia_id,photometry,start_date,end_date,version,TIME,FITMAG0,FITMAG1,FITMAG2,EPD0,…,FLAG2,HA,Z,FRAMEKEY,LCGROUP 3648155941461125760,subtracted,20230107,20230908,4,… …
hatpi_lightcurves.zip Gaia-DR2-3648155941461125760_stitched_aperphot_20230107_20230908_v1.fits Gaia-DR2-3648155941461125760_stitched_subphot_20230107_20230908_v4.fits Gaia-DR2-3648155941461125760_stitched_aperphot_20240107_20240908_v1.fits …
One FITS file per season, as stored in the HATPI archive. File names use subphot (subtracted) and aperphot (aperture).
Real response for this star, abridged (it has 5 seasons).
Season metadata is real; column values are illustrative. A season the server can't read comes back with "error": "file unavailable" instead of data.
Data service
Frames
/api/data
Find every HATPI frame whose field of view covers a sky position, optionally limited to a date range. Each result describes one exposure from one camera (IHU).
Body parameters
ranumberrequired- Right ascension in decimal degrees.
decnumberrequired- Declination in decimal degrees.
date_typestring"datetime"(default) or"JD". Sets howdate_minanddate_maxare read.date_minstring | number- Start of the date range:
YYYY-MM-DDfordatetime, a Julian Date forJD. Omit for no lower bound. date_maxstring | number- End of the date range, in the same format. Omit for no upper bound.
Query parameters
formatstringjson(default),csv, orvotable.
Response fields
JSON responses wrap results as {"total_frames": n, "frames": [...]}. CSV and VOTable return one row per frame with these columns; VOTable also labels each column with its unit, UCD, and description, which tools like TOPCAT and astropy pick up automatically.
| Field | Description |
|---|---|
object | Field name |
ihuid | Instrument Holder Unit (camera) ID |
fnum | Frame number |
datetime_obs | Observation time, UTC (ISO 8601) |
jd | Observation time as JD − 2,400,000 (note: date_min/date_max take the full JD) |
exptime | Exposure time (seconds) |
sky_background_adu | Sky background (ADU) |
moon_distance | Distance to the Moon (deg) |
sun_elevation | Sun elevation (deg) |
{
"frames": [
{
"datetime_obs": "2023-04-14T02:55:25Z",
"exptime": 30.0,
"fnum": 217927,
"ihuid": 1,
"jd": 60048.62199676,
"moon_distance": 69.17,
"object": "p1200-8400_0013",
"sky_background_adu": 2412.0,
"sun_elevation": -58.13
},
…
],
"total_frames": 16
}
object,ihuid,fnum,datetime_obs,jd,exptime,sky_background_adu,moon_distance,sun_elevation p1200-8400_0013,1,217927,2023-04-14T02:55:25Z,60048.62199676,30.0,2412.0,69.17,-58.13 p1200-8400_0013,1,217928,2023-04-14T02:56:10Z,60048.62251851,30.0,2418.74,69.18,-58.27 …
<?xml version="1.0" encoding="utf-8"?>
<VOTABLE version="1.4" …>
<RESOURCE type="results">
<TABLE>
<FIELD ID="object" arraysize="15" datatype="unicodeChar" name="object" ucd="meta.id;obs.field">
<DESCRIPTION>HATPI field name</DESCRIPTION>
</FIELD>
…
<FIELD ID="exptime" datatype="double" name="exptime" ucd="time.duration;obs.exposure" unit="s">
<DESCRIPTION>Exposure time</DESCRIPTION>
</FIELD>
…
<DATA>
<TABLEDATA>
<TR>
<TD>p1200-8400_0013</TD>
<TD>1</TD>
…
</TR>
</TABLEDATA>
</DATA>
</TABLE>
</RESOURCE>
</VOTABLE>
Real response for the request above, abridged.
Errors
The API uses standard HTTP status codes. Error bodies are JSON with a single
error message you can show to users or log.
| Status | Meaning |
|---|---|
| 200 | Success |
| 400 | Invalid request: missing or malformed parameter, too many IDs, or too many light curves |
| 401 | Missing, invalid, or revoked API key |
| 429 | Daily limit of 250 light curves reached. See Limits |
| 500 | Server error. Retry later; if the problem persists, contact the HATPI team |
{
"error": "Request matches 42 light curves (max 30). Use list_only, photometry, or season to narrow it."
}
Limits & tips
250 light curves per day
Resets at 00:00 UTC. list_only requests don't count, and your
account page shows how many you've used today.
- Use
list_onlyfirst to see a star's seasons, thenseasonandphotometryto fetch only what you need. - A single light-curve request accepts up to 25 Gaia IDs and returns up to 30 light curves; larger lists must be split across requests.
- The cURL examples save the response to a file with
-o; omit it to print the response to the terminal. - Allow a client timeout of at least 60 seconds for multi-season downloads.
Citing HATPI data
HATPI data are publicly available for immediate use. If you publish
results that use data from the API, please include this acknowledgement and cite the
project website (https://hatpi.org) until the project paper is published:
"This paper makes use of data produced by the HATPI project, located in Chile at Las Campanas Observatory of the Carnegie Institution for Science and operated by the Department of Astrophysical Sciences at Princeton University. External funding for HATPI has been provided by the Gordon and Betty Moore Foundation, the David and Lucile Packard Foundation, the Mount Cuba Astronomical Foundation, and the Agencia Nacional de Investigación y Desarrollo (ANID) of Chile through QUIMAL, Millennium and Fondecyt grants."