Base URL https://api.theweatheragent.com. All responses are JSON. Every response that carries relayed data includes an attribution string and a disclaimer field.
attribution field. Data is
provided "as is", without warranty of any kind, and may be delayed, incomplete or inaccurate.
It is not a substitute for official marine forecasts, notices to mariners, or your own
judgment. Independently verify all data against official sources before acting on it —
especially any decision affecting personal safety or navigation. Data is relayed from upstream
sources and must be independently verified — it is not the sole basis for decisions
affecting safety of life or property at sea.
Send your API key in the X-API-Key header (an Authorization: Bearer <key> header also works). Keys are issued once, at email verification, and stored only as a hash — we cannot recover a lost key, but you can issue another.
Quota is counted per account, not per key. Holding several keys does not grant additional allowance.
| Outcome | Counts as |
|---|---|
200 from a data endpoint | 1 call |
| Cache hit (same request inside the same model cycle) | 0 calls |
4xx / 429 | 0 calls |
Free tier is 10 calls/day per account, resetting at 00:00 UTC. Exceeding it returns 429 with a machine-readable quota object and a Retry-After header.
Connect your own AI agent over the Model Context Protocol at no cost. The MCP server is free to use and needs no separate plan or signup beyond an API key. Data calls it makes count toward your normal API allowance — the same per-account daily quota as REST. Metadata lookups do not.
| Tool | What it does | Counts toward quota |
|---|---|---|
get_point_forecast | Marine/weather point with a value per source | Yes — 1 call |
get_tide_extremes | Tide highs/lows for a day | Yes — 1 call when available |
generate_fishing_report | Report built from relayed data | Yes — base + 1 per ladder leg |
list_sources | Source catalog and licences | No — metadata |
get_usage | Quota readout | No — metadata |
get_disclaimer | The disclaimer, attribution and plan table | No — metadata |
Auth is required. Free does not mean anonymous — the server needs your API key so data calls are attributed to your account and quota can be enforced. There is no separate MCP price and no MCP-only upsell.
Ladder legs stay a paid feature via MCP exactly as over REST. The plan is read from your account, not from the MCP server's configuration, so it cannot be self-granted locally.
Liveness and configuration readout. Useful for status pages and uptime checks. Also carries the per-source cycle block — the upstream model cycle a downstream consumer keys its own cache on. Public and quota-free: polling it costs no calls.
The cycle block. Each enabled source reports the upstream cycle boundary currently in force, the next boundary, and seconds_to_next, so a consumer can schedule its own refresh instead of guessing. This is public and unauthenticated on purpose: polling it must not cost quota, and it is readable before your first keyed data call.
The block comes from the same function the point routes bucket their caches with, so it can never advertise a cycle the cache did not use. meta.cache_cycle on a point or batched-point response is the per-request equivalent — key your own artifacts on either; they agree.
| Field | Meaning |
|---|---|
as_of | Server time the snapshot was computed. |
sources.<id>.cycle | ISO cycle boundary in force now — the exact value used in cache keys. |
sources.<id>.next | ISO boundary of the next cycle. |
sources.<id>.seconds_to_next | Seconds from as_of to next. |
sources.<id>.cadence_minutes | Width of that source's cycle bucket (NDBC observations ~10 min, NWS hourly grids 60 min). |
| Status | Meaning |
|---|---|
200 | Service up. Inspect cache_bound / db_bound for dependency health. |
Marine and weather values at a coordinate, returned as one value per source per timestamp plus a spread/agreement statistic. Sources are never averaged into a single number.
[-90, 90].[-180, 180].waveHeight,wavePeriod,windSpeed. Unknown ids are rejected with 400, never silently dropped.1–240. Default 48.metric (default) or imperial.Available params: waveHeight, wavePeriod, waveDirection, swellHeight, swellPeriod, swellDirection, windSpeed, windDirection, windGust, airTemperature, waterTemperature, pressure, currentSpeed, currentDirection, visibility, precipitation, cloudCover.
| Status | Meaning |
|---|---|
200 | Data returned. Check meta.sources_ok / sources_failed and meta.stale. |
400 | Bad lat, lng, hours, units, or an unknown params id. |
401 | Missing or invalid API key. |
422 | No enabled source can serve the requested parameters. |
429 | Daily quota exhausted. See the 429 contract below. |
502 | Every resolved source failed. No partial or invented value is returned. |
Reading the data: spread.agree counts the sources inside an agreement band of max(param band, 10% of the median). A forecast's newest_valid is in the future by design — use newest_observation for how current the observations are. Read the spread where a spread exists: wind and atmospheric parameters are covered by two sources, so spread.n is 2 and agreement is meaningful. Wave parameters come from a single source (NDBC buoy observations), so spread.n is 1 — there is no consensus to read, and a short ladder delta sits inside one station's coverage rather than across several. Read meta.notices, meta.nearest_station and meta.spread.<param>.n before treating any wave value as more than one instrument's reading.
The same per-source values as /v2/marine/point, resolved for up to 24 coordinates in one call — a batched ladder. Every point shares one params, hours and units. Each point is resolved and reported independently, so one point failing never fails the batch.
lat,lng pairs — a comma within a point, a semicolon between points. Maximum 24 entries; 25 is rejected with 400.400-on-unknown-id rule as /v2/marine/point.1–240. Default 48.metric (default) or imperial, shared.Inline failure. A point that cannot be served appears in place in the points array as { request, error, message, failures }, with a per-source failures list, instead of failing the whole call. The HTTP status stays 200 and every other point is still returned. A point that resolves only some sources is a normal result — read meta.sources_ok / meta.sources_failed. Only when every source fails does the point become an inline error.
Each entry is the single-point shape. A successful entry is { request, hours, meta } — exactly what /v2/marine/point returns — so the same parsing code can read either route. A failed entry keeps the same request block and carries error instead of hours.
Which station answered. meta.nearest_station (and meta.stations.ndbc) names the instrument that produced the observation: id, name, distance_km, the params it actually reported, and missing_requested — the requested parameters this source could serve but that instrument does not measure. A non-empty missing_requested means no sensor, not no-data: e.g. a wind-only Gulf buoy asked for waveHeight reports missing_requested: ["waveHeight"] instead of an empty, undiagnosable result. When wave parameters are requested the resolver prefers a station that measures seas over a nearer one that does not, so read distance_km before assuming the closest station answered. Sources with no station concept (the NWS grid) contribute nothing here and leave nearest_station null.
meta.notices — stated limitations. An array of plain-language caveats that apply to this response, so a human or an agent can qualify the data instead of presenting thin coverage as solid. Two are generated today: a parameter that came from only one source (“… came from a single source — there is no cross-source spread to read…”, which is the normal case for wave parameters), and a station-based answer whose station is more than 50 km from the requested point. It is empty when nothing needs qualifying, and it is never used to soften a failure — a failure is an error, not a notice.
Billing. Only points that return fresh data are metered. A fresh point costs 1 call; a cache hit costs 0 and a failed point costs 0. batch.quota_consumed is the authoritative count for the call, and batch.cache reports miss, hit or mixed across the points. A batch of 24 fresh points is 24 calls, not 1. As with /v2/marine/point, key your own artifacts on meta.cache_cycle (see /health) — both come from the same function.
batch field | Meaning |
|---|---|
points_requested | Entries parsed from points. |
points_ok | Points that returned data. |
points_failed | Points with an inline error. |
cache | miss, hit or mixed across the batch. |
cache_hits | Points served from cache. |
quota_consumed | Calls billed — fresh data-bearing points only. |
upstream_ms | Wall time spent resolving the batch upstream. |
| Status | Meaning |
|---|---|
200 | Batch processed. Inspect batch.points_ok / points_failed and each point's inline error. |
400 | Bad grammar, a coordinate out of range, more than 24 points, or an unknown params id. Reported as points entry N: .... |
401 | Missing or invalid API key. Same gate as /v2/marine/point. |
429 | Daily quota exhausted. See the 429 contract below. |
Planned (P1). High/low tide times and heights for a day, relative to MSL, units stated. Documented here so the surface is known; the MCP tide tool reports it as not-yet-available rather than inventing data.
The source catalog: id, dataset, resolution, cadence, area, licence, whether commercial use is permitted, and whether attribution is required. Use this to render correct attribution.
UK Met Office is deliberately excluded: its global wave product is CC-BY-SA (share-alike), which is incompatible with our terms through MVP.
Returns the current disclaimer and attribution strings. If you cache or re-serve our data, fetch these and attach them — they change when the source set changes.
Create an account and send an email verification link. The free tier is gated on a verified address. Request JSON: { "email": "[email protected]", "device_fp": "optional" }.
| Status | Meaning |
|---|---|
202 | Verification email sent (or re-sent). |
400 | Missing or invalid email address. |
409 | That address already has a verified account. |
429 | Too many new accounts created from this connection recently. |
503 | Accounts store unavailable. |
Note: outbound email delivery is deferred, so verification currently runs on a log transport and the response includes a dev_verify_url. That field disappears once a real mail provider is configured.
Consume a verification token and issue an API key. Tokens are single-use and expire after 24 hours (the optional query parameters token and web are accepted; web=1 renders a short HTML confirmation page instead of JSON).
| Status | Meaning |
|---|---|
200 | Verified; key issued. This is the only time the key is shown. |
400 | token missing, invalid_token, token_expired, or token_already_used. |
Quota readout: used, limit, resets_at, plan, plus the definition of what counts as a call.
List your keys, or issue an additional one. A key's secret is returned only at creation.
| Status | Meaning |
|---|---|
401 | Missing or invalid API key. |
Quota is per account: additional keys do not add allowance.
Revoke a key. Revocation is immediate and the key stops resolving on the next request.
| Status | Meaning |
|---|---|
200 | Revoked. |
401 | Missing or invalid API key. |
404 | No such active key on your account. |
Quota exhaustion is machine-readable. The body carries a quota object and the response carries a Retry-After header in seconds.
A fishing report is metered per leg: the base report is 1 call, tide adds 1, and each ladder leg you request adds 1. Ladder legs are optional and user-specified, so a report's total depends on what you ask for — there is no fixed report cost. Ladder legs require a paid plan.
| Shape | Notes |
|---|---|
{ "error": "...", "message": "...", "request_id": "..." } | Errors also carry attribution and disclaimer. |
404 | Body echoes the method actually received, e.g. No route for GET /v2/auth/signup. A wrong-method request reports the method Hono saw, which is the fastest way to diagnose a probe that sent the wrong verb. |