Insurers, reinsurers, brokers
Risk index and signed exports
The insurer product: the 0 to 100 index per peril, the bay aggregation and suppression rules, the CSV export, verifying its Ed25519 signature with a complete Python example, and how to cite the licences.
Last reviewed
The insurer product
The bay risk index is one value from 0 to 100 per bay, UTC day and peril, built from the signals already computed for the bay's sites. It is designed for underwriting and portfolio monitoring: regional, anonymised and reproducible.
| Peril | Signals read |
|---|---|
thermal | signal:thermal (level, degree_days_14d) |
bloom | signal:bloom (index) |
runoff | signal:runoff (level, salinity_drop_48h_psu, rain_24h_mm) |
storm | signal:operability 6h bins (hs_m, wind_kn only); event:storm (daily peak at the bay reference cell) |
Per site and day each peril gets a score from 0 to 100 (the break points are in the help article How the risk index is built). The method version is risk-index/2 and travels in every row.
Bay aggregation and suppression
- For each bay, day and peril the index is half the worst site's score plus half the mean of the sites' scores, rounded to 0.1. Level: below 40 low, below 70 watch, below 85 stress, otherwise critical.
- A day and peril with fewer than 3 contributing sites is suppressed:
index,site_maxandsite_meanare null,suppressedis true and onlyn_sitesis kept, so a bay figure never stands for one or two identifiable farms. - No site id, name, licence number or position appears in a row or an export. The worst site is a value, never a site. The storm peril reads only physical wave height and wind, never a farm's working limits; a bay storm event sets a floor under that day's storm index.
Getting the index
- REST:
GET /agency/risk-index?bay=&from=&to=(productrisk_index), one row per day and peril in the envelope described on the REST API page, withmethodandmin_sitesadded. - MCP: tool
get_risk_indexwithbay,from_date,to_date; see the MCP server page. - Signed CSV:
GET /bays/{bay_id}/risk-index?from=&to=&format=csvwith the same key, the same checks and the same access-log row. Withoutformatit returns the JSON envelope.
| Row field | Meaning |
|---|---|
bay_id, date, peril | The bay, the UTC day and the peril (thermal, bloom, runoff, storm). |
index | 0 to 100, rounded to 0.1; null when suppressed or when the bay had no data that day. |
level | low (below 40), watch (below 70), stress (below 85), critical; null with the index. |
n_sites | Sites with a value that day. Kept even when the row is suppressed. |
site_max, site_mean | The worst site's score and the mean of the sites' scores, never which site; null when suppressed. |
suppressed | true when fewer than the minimum number of sites contributed: index, site_max and site_mean are null. |
confidence | The lowest confidence among the contributing values (high, medium, low). |
lead_hours | 0 for an analysis day, above 0 for a forecast day. |
source, product, scale, licence | coastal-intel, risk_index:<peril>, regional, and the licence ids of the inputs. |
inputs, method | Which signals were read and the method version, so a figure can be reproduced later. |
The CSV export
One header line, then one line per day and peril, an empty cell for null, columns in this order: bay_id, date, peril, index, level, n_sites, site_max, site_mean, suppressed, confidence, lead_hours, source, product, scale, licence, inputs, method. The file name is risk-index-<bay>-<from>_<to>.csv (Content-Disposition) and the response is marked Cache-Control: no-store.
curl -D headers.txt -o risk-index.csv -H "Authorization: Bearer $AGENCY_KEY" \ "https://coastal-intelligence.triskelionaisystems.com/api/bays/<bay id>/risk-index?from=<YYYY-MM-DD>&to=<YYYY-MM-DD>&format=csv"
Keep the response headers with the file: they are the signature.
Verifying the signature
The bytes of every CSV export are signed with Ed25519. The response carries X-Content-SHA256, X-Signature, X-Signature-Alg, X-Signature-Key-Id. The public key is served without a key at GET https://coastal-intelligence.triskelionaisystems.com/api/exports/signing-key as {algorithm, key_id, public_key, development}, where public_key is the base64 of the raw 32-byte key. A key_id starting with dev- (and development: true) is the fixed development key: such a signature proves nothing outside development, and a verifier should refuse it.
A complete check in Python (standard library plus the cryptography package):
import base64
import hashlib
import json
import urllib.request
from cryptography.exceptions import InvalidSignature # pip install cryptography
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
API = "https://coastal-intelligence.triskelionaisystems.com/api"
KEY = "<your key>" # read it from the environment in real code
BAY, FROM, TO = "<bay id>", "<YYYY-MM-DD>", "<YYYY-MM-DD>"
# 1. the signed CSV and its headers
req = urllib.request.Request(
f"{API}/bays/{BAY}/risk-index?from={FROM}&to={TO}&format=csv",
headers={"Authorization": f"Bearer {KEY}"},
)
with urllib.request.urlopen(req) as res:
body = res.read()
headers = dict(res.getheaders())
# 2. the public key (no key needed)
with urllib.request.urlopen(f"{API}/exports/signing-key") as res:
signing = json.load(res)
# 3. checks: algorithm and key id match, the digest matches, the signature verifies
assert headers["X-Signature-Alg"] == signing["algorithm"] == "ed25519"
assert headers["X-Signature-Key-Id"] == signing["key_id"]
assert hashlib.sha256(body).hexdigest() == headers["X-Content-SHA256"]
public = Ed25519PublicKey.from_public_bytes(base64.b64decode(signing["public_key"]))
try:
public.verify(base64.b64decode(headers["X-Signature"]), body)
except InvalidSignature:
raise SystemExit("the file was altered or is not from this server")
if signing["development"]:
print("warning: a development signing key; this signature proves nothing outside development")
with open(f"risk-index-{BAY}-{FROM}_{TO}.csv", "wb") as f:
f.write(body) # keep the file and the X-Signature header togetherAny Ed25519 library works the same way: decode public_key and X-Signature from base64 and verify the signature over the exact bytes of the file. Re-encoding the CSV (line endings, a spreadsheet save) breaks the signature by design.
Citing the licences and attribution
Every row's licence names the licences of its inputs, and the JSON envelope lists them with the exact attribution lines they require. When you publish or pass on a figure, a chart or a file, keep those lines and the method version. The licences this deployment can return:
copernicus_marine: Copernicus Marine Service licence (free, full and open), E.U. Copernicus Marine Service.copernicus_sentinel: Legal notice on the use of Copernicus Sentinel Data and Service Information, European Union / ESA, Copernicus Data Space Ecosystem.copernicus_c3s: Licence to use Copernicus Products (Copernicus Climate Change Service, C3S), Copernicus Climate Change Service / ECMWF.ecmwf_open_data: Creative Commons Attribution 4.0 International (ECMWF open data), ECMWF.marine_institute: Creative Commons Attribution 4.0 International (Marine Institute, Ireland), Marine Institute, Ireland.epa_ireland: Creative Commons Attribution 4.0 International (EPA, Ireland), Environmental Protection Agency, Ireland.
The CSV has no envelope: take the attribution lines from the JSON form of the same call (or from GET /datasets) and cite them with the file. Details on the Data model and licences page.
The index is regional: model and satellite inputs, verified in the bay only where a station allowed it. Only the bloom signal has a recorded back-test so far. It is an indicator for a named activity, not food-safety advice and not a warranty of conditions: official closures (Marine Institute HAB bulletin, SFPA) and observations prevail.
Related
REST API
The base URL of this deployment, every partner endpoint with its parameters, the date rules, the response envelope field by field, examples in curl, Python and JavaScript, and the live OpenAPI reference.
Last reviewed 1 Nov 2026Analysts with an AI assistant, agent buildersMCP server
The Model Context Protocol server for AI assistants and agents: endpoint and transport, the auth header, every tool with its typed arguments, the tool-error shape, client configurations, the configuration checker and example prompts.
Last reviewed 1 Nov 2026Data engineers, legal and complianceData model and licences
The five provenance fields on every row, the three scales, what lead_hours means, the public dataset registry, the licence ids and the attribution line each one requires, and the product catalogue.
Last reviewed 1 Nov 2026