HTTP API¶
Beta
This API is a beta version. Endpoints, parameters and responses can change without notice.
A read-only HTTP API over the same analytics engine that powers the Summix application. It is in closed beta: access is granted per user, and the contract can change without notice.
Getting a key¶
Open your profile page and choose Create API key. The key is shown once — store it somewhere safe. The key is personal: it acts as you, so never share it. You can revoke it from the same page at any time; a revoked key stops working immediately.
Send it as a bearer token on every request:
curl -H "Authorization: Bearer $TIPSPEED_API_KEY" \
https://v2.tipspeed.com/api/beta/projects/
Inform your agent¶
A coding agent (Mistral, Claude Code, Cursor, …) works best from the machine-readable contract rather than this page. The schema is served with the same key as the data, so tell your agent:
Fetch the Tipspeed API contract before writing any code:
curl -H "Authorization: Bearer $TIPSPEED_API_KEY" https://v2.tipspeed.com/api/beta/openapi.json
Then call GET /api/beta/catalogue/ for the metric keys and signal names.
Keep the key out of the prompt and out of your code. Store it in a password manager, and expose it
to your project as the TIPSPEED_API_KEY environment variable — typically from a .env file that
is listed in .gitignore, so it is never committed. The agent then refers to the variable, and the key
itself is never pasted into the conversation.
The schema is always current, so there is no file to keep in sync. If you would rather hand the agent a file, download the OpenAPI schema.
The five operations¶
| Operation | What it answers |
|---|---|
GET /api/beta/projects/ |
Which projects you can see, and over what date range. Call this first — it gives you the team_slug and project_slug every other call needs. |
GET /api/beta/catalogue/ |
Every metric you can ask for: key, unit, aggregation, formula, dependencies, and bin_width (non-null means the metric can be binned). |
GET /api/beta/projects/{team}/{project}/query |
Any metric, over any combination of the turbine, period and bin dimensions, optionally filtered by a signal's value. |
GET /api/beta/projects/{team}/{project}/turbines |
One row per turbine: statics, plus any metrics you ask to have joined on. |
GET /api/beta/projects/{team}/{project}/energy-chain-summary |
The gross-to-net energy waterfall for a date range. |
Querying¶
/query takes an explicit list of metric keys and three independent dimension controls. Every
registered metric supports by_turbine and period; a metric can additionally be used as bin_by
when the catalogue gives it a non-null bin_width.
# farm production and performance ratio, month by month
curl -H "Authorization: Bearer $TIPSPEED_API_KEY" \
"$BASE/api/beta/projects/acme/northfield/query?metrics=production_100pct_avail,performance_ratio&period=1mo"
# per-turbine production, binned by wind speed
curl -H "Authorization: Bearer $TIPSPEED_API_KEY" \
"$BASE/api/beta/projects/acme/northfield/query?metrics=production_100pct_avail&by_turbine=true&bin_by=wind_speed"
# only the rows where the modelled wind speed was between 8 and 12 m/s
curl -H "Authorization: Bearer $TIPSPEED_API_KEY" \
"$BASE/api/beta/projects/acme/northfield/query?metrics=production_100pct_avail&filter_by=wind_speed_optimized_model&filter_min=8&filter_max=12"
filter_by takes a signal name, not a metric key — the two are different namespaces. The
catalogue lists the legal values under signals; metric keys are under metrics. For a source
signal (like wind_speed_optimized_model above), the catalogue entry's column and model say
which underlying quantity and model it comes from — that's how you know the bound is in m/s.
Each row carries time, turbine and bin — null on any dimension you did not request — plus a
values object keyed by metric key.
period is one of 10min, 1h, 1d, 1mo, 1y and all, and defaults to 1d: a query without
it returns one row per day. Pass period=all for a single row totalling the whole date range. time
labels each period in UTC — 2026-01-01T10:20Z for 10min and 1h, 2026-01-01,
2026-01 and 2026 for the others, and null for all. A 10min label is the timestamp of the
underlying 10-minute record, which marks the end of the interval it covers, while 1h and
coarser periods are labelled by their start — see
what a timestamp means. Periods without any data
are left out rather than returned with null values. 10min accepts at most 31 days between start
and end, and 1h at most 366; a longer window is refused with 400, so pass start/end with
them.
start and end are UTC dates, and end is exclusive. Every response echoes the window it actually
covered as start and end, which tells you what was totalled when you left them out.
# one turbine's wind speed, 10 minutes by 10 minutes, for January 2026
curl -H "Authorization: Bearer $TIPSPEED_API_KEY" \
"$BASE/api/beta/projects/acme/northfield/query?metrics=wind_speed&period=10min&by_turbine=true&turbines=T01&start=2026-01-01&end=2026-02-01"
Rate limits¶
60 requests per minute and 1000 per day, counted per API key. Over the limit the API answers 429;
wait and retry.
Errors¶
| Status | Meaning |
|---|---|
400 |
Malformed query: unknown metric key, a bin_by that is not binnable, filter bounds without a filter_by, or an inverted range. The body says which. |
401 |
No key, an invalid or revoked key, or a key whose user is not in the beta. |
404 |
The project does not exist, or is not one you can see. |
422 |
A required parameter is missing — metrics on /query, for instance. |
429 |
Rate limited. |
An empty rows list means either that no data falls in the range or that the project has no
published dataset. The two are not distinguished today.