Skip to content

Archive Router

The /archive router provides read-only access to the SeisComp Data Structure (SDS) archive written by the daemon’s MSeedWriter thread. All heavy lifting is done inside the ArchiveHelper class, which is shared across endpoints.


Liveness check. Returns the resolved SDS and StationXML paths and whether they exist on disk.

No parameters.


Scan the SDS tree and return every distinct channel code present for the configured network/station.

Response: string[] — e.g. ["EHE","EHN","EHZ"]

GET /archive/channels
→ 200 ["EHE","EHN","EHZ"]
404 {"detail":"No channels found in archive"}
503 {"detail":"SDS root not found: …"}

Return ISO dates (YYYY-MM-DD) for which at least one SDS day file exists for the requested channel.

ParameterTypeRequiredDescription
channelstringChannel code, e.g. EHZ

Response: string[] sorted oldest-first — e.g. ["2026-01-01","2026-01-02"]


Single-channel waveform fetch with optional instrument-response removal.

ParameterDefaultDescription
channelChannel code
startISO-8601 start time
endISO-8601 end time
unitsCOUNTSCOUNTS | VEL | DISP | ACC
max_pts4000Max display points (100–20,000)

Response shape:

{
"channel": "EHZ",
"network": "XX",
"station": "RPI3",
"units": "counts",
"fs": 25.0,
"starttime": "2026-04-01T00:00:00.000000Z",
"endtime": "2026-04-01T00:05:00.000000Z",
"npts_raw": 30000,
"npts_display": 4000,
"data": [12345, 12346, ]
}

Multi-channel waveform fetch. All channels are read concurrently using asyncio.gather; latency is bounded by the slowest channel, not the sum.

Channels with missing data are reported in errors without aborting the whole request.

ParameterDefaultDescription
channelsRepeat param: ?channels=EHZ&channels=EHN
startISO-8601 start
endISO-8601 end
unitsCOUNTSCOUNTS | VEL | DISP | ACC
max_pts4000Per-channel display point cap

Response shape:

{
"results": [ { …waveform… }, { …waveform… } ],
"errors": [ { "channel": "EHE", "detail": "No data for EHE …" } ]
}

Export a time window in one of four formats, packaged as a ZIP archive.

ParameterDefaultDescription
channelsRepeat param (same as /waveforms)
startISO-8601 start
endISO-8601 end
unitsCOUNTSSame options as /waveforms
fmtmseedmseed | sac | csv | json

Response: application/zip with one file per channel.

Full-resolution MiniSEED trimmed to the requested window. Opens in ObsPy, SeisComP, or any FDSN-compliant tool. Record length: 512 bytes (Steim-2 compatible).


Return SDS day-file metadata records for a specific channel and date.

ParameterDefaultDescription
channelChannel code
dateYYYY-MM-DD
limit100Max records to return (1–1000)

Response: list[{date, channel, filename, size_kb}]


Stream a raw MiniSEED day file directly to the browser as a download.

ParameterDescription
channelChannel code
dateYYYY-MM-DD

Response: application/octet-stream — the unmodified SDS day file.


When units is anything other than COUNTS, the API applies a full deconvolution pipeline on the server before returning data:

  1. Demean — remove DC offset that would blow up in the frequency domain.
  2. 5 % cosine taper — suppress Gibbs ringing at trace edges.
  3. remove_response — divide by the PAZ + ADC transfer function using a cosine pre-filter.
  4. SI → nm conversion — multiply by 1e9 to avoid tiny floats on the Y axis.

Pre-filter corners (Hz): (0.5, 1.0, 45.0, 48.0) — zero below 0.5 Hz, full pass 1–45 Hz, zero above 48 Hz.

Water level: 60 dB — stabilises division near the zeros of the response.

The station.xml inventory is cached in memory and re-read from disk only when the file’s mtime changes, so epoch updates take effect on the next request without an API restart.


LimitValue
Max samples per request200,000
Max time window6 hours
Max display points (decimated)20,000
Peak-decimation target (export JSON)4,000

Requests that exceed these limits receive a 400 Bad Request with an explanatory message.


For display endpoints the API uses peak-preserving decimation rather than a low-pass filter downsample. In each chunk the sample with the largest absolute value is retained, ensuring earthquake peaks survive visualization even at aggressive decimation ratios.

factor = int(len(data) / target)
chunks = data[:trim].reshape(-1, factor)
idx = np.argmax(np.abs(chunks), axis=1)
return chunks[np.arange(len(chunks)), idx]

This is intentionally different from the daemon’s anti-alias decimation — for display you want extremes preserved, not smoothed away.