Evidence Object v1
The planned structured contract for each claim in a Senlay response. It keeps the value, unit, source, timestamp, distance, freshness, confidence, uncertainty, and disagreement visible instead of hiding them in a generic answer.
Evaluation beta. Commercial Open-Meteo access has not been arranged. Confirm commercial source rights and configuration before commercial deployment; actual availability depends on current deployment settings. The API is not flight or mission clearance.
Senlay is an evaluation beta for teams building drone software. Its current workflow returns available wind observations and forecasts for a coordinate, with source, timestamp, distance, disagreement, and uncertainty for operator review. The first buyer is a drone software team; the demand and repeatable value remain hypotheses to validate. SmartSurf is the product's origin and reference experience. Begin with the robotics integration overview for current capability boundaries. Each request depends on the sources available at its coordinate.
The Physical World Model (PWM) returns available environmental evidence for a coordinate. The catalog lists 23 source-family entries; entries are adapters or provider families, not a count of live sources at a coordinate. Actual configured, returned, and unavailable sources are reported separately.
The Senlay layer stack adds a versioned catalog for live sensors, forecast models, terrain elevation, satellite visual context, hazards, and risk operations, plus planned bathymetry, land cover/roughness, buildings/obstacles, coastline/access, and telemetry layers. Runtime status explicitly distinguishes active data from layers that are not loaded. Heavy static layers require background preprocessing and compact cached spot summaries.
For developer workflows, the response can include a pre-formatted context_string with available evidence and limits. Pass it to an LLM as data/tool output under your application's instructions. For workflows such as SmartSurf, Senlay can also produce risk_event records for alertable and auditable operational context.
Measured observations vs. predictions. METAR stations, ocean buoys, and tide gauges produce measured readings. Weather models produce predicted values. When they disagree, Senlay reports the available values and relevant freshness, distance, data quality, and uncertainty; an instrument reading is not automatically ground truth.
Robotics telemetry examples. The project includes read only reference adapters for CRC-checked MAVLink 1/2 position frames over UDP and ROS 2 sensor_msgs/msg/NavSatFix through rosbridge. They use the existing authenticated GET /api/v1/pwm endpoint and do not issue robot commands. ROS 2 and rosbridge are separate prerequisites; the examples do not convert local-coordinate messages, authenticate MAVLink senders, evaluate routes, or provide safety clearance. See the adapter details and limits.
Node.js 22; no npm install. Download senlay-robotics-v0.1.0.zip, then run:
unzip senlay-robotics-v0.1.0.zip cd senlay-robotics-v0.1.0 node examples/robotics/robotics-context.mjs --transport replay
The replay position and environmental values are synthetic, with no key, network, hardware or robot commands. For live MAVLink UDP or ROS 2 rosbridge, follow the bundled README and transport requirements, shared API limits and capability boundaries.
| What endpoint should an agent call? | Use /api/v1/try-sense for a no-key browser trial, /api/v1/sense for authenticated plain text, and /api/v1/pwm for structured JSON. |
| What parameters are required? | lat and lng are required. field and request improve domain interpretation. |
| What does the response contain? | Measured/model conditions, source evidence, freshness, confidence, disagreement, decision_context, modifiers, and context_string. |
| How do safety apps consume alerts? | Use /api/v1/risk-events and /api/v1/risk-events/recent for operational risk records suitable for SmartSurf-style station, lifeguard, and audit workflows. |
| How do agents inspect the layer stack? | Use /api/v1/layers/catalog for provider/layer metadata and /api/v1/layers/context for a coordinate-specific layer context. |
| What happens when data is missing? | Senlay returns the available context and should expose uncertainty. Agents should not invent missing measurements. |
How should an LLM use context_string? | Pass it as data/tool output under the application's instructions. Preserve source, time, distance, disagreement, and unknowns. It is decision support, not flight or mission clearance. |
Current PWM responses expose provenance across fields such as current_source, source_use, per-layer source labels, timestamps, modifiers, and decision context. The example below is a synthetic concept sketch, not a current response schema or a promise that every field is returned.
{
"claim": "Wind speed observations differ from the model",
"value": 18,
"unit": "km/h",
"evidence_type": "synthetic_observation",
"source": {
"type": "sample_station",
"id": "SYNTHETIC-01",
"distance_km": 4.2,
"timestamp": "2026-01-15T12:00:00Z"
},
"model_value": 12,
"model_timestamp": "2026-01-15T12:00:00Z",
"difference_kmh": 6,
"model_disagreement": {
"status": "values_differ"
},
"interpretation": "Synthetic example only; inspect source quality and representativeness.",
"uncertainty": "Distance, calibration, and local conditions may limit relevance."
}
The proposed, versioned Evidence Object is a roadmap item; check the roadmap for its status. Use the current API response and OpenAPI contract for integration.
The pre-formatted context_string summarizes available evidence. This synthetic wind illustration is not live data and does not establish a trend:
SYNTHETIC EXAMPLE — NOT CURRENT DATA At 2026-01-15 12:00 UTC, a sample station 4.2 km away reports wind at 18 km/h; a model value for the same valid time is 12 km/h. The values differ by 6 km/h. Check timestamps, calibration, and representativeness. A single comparison does not establish a trend.
Authenticated API endpoints require a Bearer token. The public /api/v1/try-sense endpoint is a limited no-key trial for browser-based chat agents.
Authorization: Bearer sl_live_your_key_here
See current beta access and limits, then create an account and API key for authenticated requests. A key does not grant commercial source rights.
For a drone wind evidence review, request the wind profile explicitly. This example reports the HTTP status before interpreting a response; a non-2xx response is an API error, not evidence.
import os
import requests
url = "https://senlay.cloud/api/v1/pwm"
params = {"lat": 37.6213, "lng": -122.3790, "field": "drone", "profile": "wind"}
response = requests.get(url, params=params, headers={"Authorization": f"Bearer {os.environ['SENLAY_API_KEY']}"}, timeout=20)
print("HTTP", response.status_code)
if not response.ok:
raise RuntimeError(f"Senlay API error {response.status_code}: {response.text}")
data = response.json()
assessment = data.get("risk_assessment", {})
print("outcome:", assessment.get("outcome", data.get("outcome")))
print("evaluation_scope:", assessment.get("evaluation_scope", data.get("evaluation_scope")))
print("unknowns:", assessment.get("unknowns", data.get("unknowns", [])))
for layer_name, layer in data.get("pwm", {}).get("layers", {}).items():
source = layer.get("current_source") or {}
print(layer_name, source.get("source"), source.get("timestamp"), source.get("distance_km"))For a chat model that can browse but cannot send POST bodies or Bearer headers, use the rate-limited no-key evaluation URL:
https://senlay.cloud/api/v1/try-sense?lat=37.6213&lng=-122.3790&field=drone&agentName=ExampleAgent
For a self-updating browser view of the same request, open the live page URL:
https://senlay.cloud/agents/live?lat=37.6213&lng=-122.3790&field=drone&agentName=ExampleAgent&request=Summarize%20available%20wind%20evidence%20and%20unknowns%20for%20operator%20review
For repeated beta evaluation requests, create a free key and call the authenticated API. A key does not grant commercial source rights or establish production readiness.
curl -H "Authorization: Bearer sl_live_your_key" \ "https://senlay.cloud/api/v1/pwm?lat=36.01&lng=-5.60&field=drone&profile=wind"
For plain text output (no JSON parsing needed):
curl -H "Authorization: Bearer sl_live_your_key" \ "https://senlay.cloud/api/v1/sense?lat=36.01&lng=-5.60&field=drone"
Connect an MCP-capable agent directly to https://senlay.cloud/mcp. Anonymous evaluation access needs no installation, account, or OAuth flow. Add an optional Senlay API key as a Bearer header to use the key owner's published beta allowance. The four tools are sense_location, check_operability, list_domains, and get_forecast_trust.
{
"mcpServers": {
"senlay": {
"url": "https://senlay.cloud/mcp"
}
}
}
The server uses stateless Streamable HTTP. The MCP SDK negotiates a compatible protocol version during initialize; clients should not rely on a fixed version in health metadata. It exposes four tools:
| Tool | Purpose |
|---|---|
sense_location | Evidence and provenance for current physical conditions, including source distance, age, measured/predicted status, confidence, divergence, and unavailable evidence. |
check_operability | Domain-specific deterministic risk events, thresholds, exceeded conditions, unknowns, and assessment uncertainty. Decision support only; humans remain the final authority. |
list_domains | Static list of supported operational domains and a brief of their evidence/threshold logic. |
get_forecast_trust | Historical forecast reliability by wind speed and direction; returns UNKNOWN until eligible archived forecast and instrument pairs are sufficient. |
For authenticated use, configure the same URL with Authorization: Bearer sl_live_your_key. Treat historical forecast trust as UNKNOWN unless the response establishes it. Anonymous limits return a direct link to POST /api/v1/agent-register. The optional time input currently accepts only present-time requests; historical and future requests fail explicitly rather than being silently treated as current.
Public, no-key evaluation endpoint for chat agents with browsing. It returns plain text, includes usage guidance, and is rate-limited. Use it to inspect currently available source context; coverage and freshness vary, and a response may contain gaps or no usable observation.
https://senlay.cloud/api/v1/try-sense?lat=36.01&lng=-5.60&field=drone&agentName=MyChatAgent
| Parameter | Required | Description |
|---|---|---|
lat | Yes | Latitude (-90 to 90) |
lng | Yes | Longitude (-180 to 180) |
field | No | Reasoning mode, for example kitesurfing, drone, sailing, agriculture, running, or general |
agentName | No | Human-readable name shown in the trial response |
request | No | Agent/user task embedded into the response so the model can answer with the correct field context |
view | No | Use view=live to open the self-updating HTML page instead of the plaintext response |
The same live page is also available at /agents/live. It stores state in the URL, so parallel agents can use different agentName, field, request, and session values without overwriting each other.
Trial mode is intentionally limited: 8 requests/minute burst and 60 requests/hour per IP. The live page clamps automatic refresh to 120-600 seconds. For repeated use or automation, register an agent and use /api/v1/sense with Bearer auth.
Structured Physical World Model JSON containing the data that was available for this coordinate, plus source health, extended observations/feeds, satellite context, and the pre-formatted context string. Individual layers can be disabled, out of coverage, stale, or unavailable.
| Parameter | Required | Description |
|---|---|---|
lat | Yes | Latitude (-90 to 90) |
lng | Yes | Longitude (-180 to 180) |
field | No | Optional reasoning mode used when building context_string |
profile | No | Use profile=wind for the defined wind evidence profile. It does not add route, aircraft, obstacle, weather-clearance, or mission evaluation. |
{
"status": "ok",
"active_sources": 7,
"total_sensors": 3,
"pwm": {
"coordinates": { "lat": 36.01, "lng": -5.60 },
"timestamp": "2026-04-09T12:00:00Z",
"layers": {
"atmosphere": {
"current": {
"wind_speed_10m": 33, "wind_gusts_10m": 61.9,
"wind_direction_10m": 84, "temperature_2m": 16.5,
"pressure_msl": 1019.5, "humidity": 48, "cloud_cover": 3
}
},
"hydrosphere": {
"current": {
"wave_height": 1.2, "wave_period": 8.3,
"swell_wave_height": 0.8
}
},
"terrain": {
"elevation_at_point": 18,
"profile_kind": "terrain_elevation",
"bathymetry_available": false,
"is_ocean": false,
"vertical_datum": null
},
"air_quality": {
"current": {
"pm2_5": 12.3, "pm10": 18.7,
"uv_index": 6.2, "european_aqi": 42
}
}
},
"health": [
{ "source": "base_pwm", "status": "ok", "has_data": true },
{ "source": "ndbc_buoys", "status": "no_data", "has_data": false }
]
},
"extended": {
"wind_sensors": [
{ "source": "metar", "name": "Rota NAS",
"distance_km": 96.8, "wind_speed_kmh": 11.1,
"is_hardware": true }
],
"wind_cross_reference": {
"sensor_count": 2, "average_kmh": 22,
"confidence": "moderate"
},
"buoys": [],
"tides": {
"station_id": "9410230",
"current_level_m": 1.2,
"next_high": { "time": "14:30", "height_m": 1.8 }
},
"earthquakes": [],
"fires": []
},
"satellite": {
"sentinel2": {
"available": true, "date": "2026-04-07",
"cloud_cover": 12
}
},
"context_string": "=== SENLAY PHYSICAL WORLD MODEL === ..."
}
| Field | Type | Description |
|---|---|---|
status | string | "ok" on success |
active_sources | number | Count of sensor sources that returned data |
pwm | object | Raw source data with available atmosphere, hydrosphere, terrain, air-quality, extended, satellite, and health fields |
extended | object | Hardware observations plus official alert, event, hazard, and optional-provider data |
satellite | object | Sentinel-2 imagery metadata |
pwm.health | array | Per-source latency, availability, and status report. It is nested inside pwm on this authenticated endpoint. |
layer_context | object | Versioned layer-stack status, terrain/marine/wind/risk context, missing next layers, and cache/precompute actions |
context_string | string | Pre-formatted summary of available context; provide as data/tool output and preserve its source limits |
?view=evidence, ?view=risk_events, and ?view=full on this endpoint (and /api/v1/evidence, /api/v1/risk-events) all carry the same risk_assessment.outcome/unknowns/confidence_components/conflicts fields described under GET /api/v1/risk-events.
The layer endpoints expose the product-level stack that Senlay uses to explain current and planned physical-world context. Public demo equivalents are available at /api/layers/catalog and /api/layers/context; authenticated API clients should use the /api/v1 paths with a Bearer key.
curl -H "Authorization: Bearer sl_live_your_key" \ "https://senlay.cloud/api/v1/layers/catalog"
Returns layer metadata, recommended providers, status, cadence, license notes, output fields, and the request-time policy. The catalog includes active runtime providers and planned static providers; each entry states its access and deployment status. Open-Meteo layers are conditional on a paid customer key or compliant configured host; OpenAQ v3 and NASA FIRMS also require credentials. Heavy sources such as GEBCO and WorldCover remain planned until preprocessed and loaded. Even when loaded, the coarse GEBCO grid can provide regional depth/gradient context but cannot identify spot-scale reefs, sandbars, or obstructions and is not a navigation chart.
curl -H "Authorization: Bearer sl_live_your_key" \ "https://senlay.cloud/api/v1/layers/context?lat=36.0143&lng=-5.6044&field=kitesurfing"
Returns the current coordinate-specific layer status plus derived terrain, marine, wind, sensor, and risk context. Missing heavy layers are reported as next actions instead of being loaded synchronously.
Simplified endpoint — returns only the context_string as plain text. Content-Type: text/plain. Ideal for agents that don't want to parse JSON.
Requires lat and lng; optional field selects the reasoning mode. profile is supported by /api/v1/pwm, not this plain-text endpoint.
curl -H "Authorization: Bearer sl_live_your_key" \ "https://senlay.cloud/api/v1/sense?lat=36.01&lng=-5.60&field=drone"
Returns the Physical World Model as a plain text block. No parsing is required. Pass it as data/tool output under your application's instructions, preserve source and uncertainty, and do not treat it as clearance for physical action.
Authenticated endpoint for operational risk events. Use it when an application needs more than context text: a station dashboard, lifeguard workflow, fleet monitor, school safety view, or IoT alert pipeline can read structured events that summarize the detected risk, severity, coordinates, sources, and recommended review path.
SmartSurf is the first proving ground: Traccar GPS movement and local triggers identify a possible rider or board problem, then Senlay adds environmental evidence before the system escalates or stays quiet. The endpoint is decision support, not a certified rescue authority.
Risk responses can also include risk_assessment: an aggregate deterministic state with score, alert band, confidence, reasons, recommended action, escalation stage, incident state, source provenance, session phase, and field-validation metadata. This is the SmartSurf early-warning contract: it is meant to show recoverability risk and coordination needs, not to diagnose drowning or claim rescue dispatch.
risk_assessment.outcome is one of GO, CAUTION, NO_GO, or INSUFFICIENT_EVIDENCE. The last one is a normal, successful result (HTTP 200), not an error: it means the evidence does not support a verdict, and risk_assessment.unknowns names the specific blocking variable(s), why (no coverage, sources conflict, stale, or missing entirely), and what would resolve it. Confidence is also decomposed into risk_assessment.confidence_components — source_agreement, freshness, spatial_relevance, and evidence_coverage — each with its own label and reason string, rather than one blended score. When hardware and model sources disagree, the disagreement is reported as a structured risk_assessment.conflicts entry (each contributing source's value, distance, and age, plus the delta and magnitude) instead of being averaged away.
| Endpoint | Use |
|---|---|
GET /api/v1/risk-events | Current active operational risk events. |
POST /api/v1/risk-events | Derive current risk events from coordinates plus optional tracker, station, or geofence context. |
GET /api/v1/risk-events/recent | Recent persisted events for audit, review, and station logs. |
GET /api/v1/risk/taxonomy | SmartSurf alert bands, hazard families, MVP-detectable signals, later Senlay phases, and wording boundaries. |
curl -H "Authorization: Bearer sl_live_your_key" \ "https://senlay.cloud/api/v1/risk-events?lat=15.8801&lng=108.3380&field=kitesurfing"
lat and lng are required for the current risk endpoint. It derives the current event set for that coordinate; status is not a supported query filter. Use /api/v1/risk-events/recent for persisted records and its documented type, severity, subject, time-window, and location filters.
{
"type": "rider_stopped_offshore",
"severity": "monitor",
"status": "active",
"lat": 15.8801,
"lng": 108.3380,
"source": "smartsurf",
"evidence": {
"movement": "stopped_or_drifting",
"distance_from_shore_m": 820,
"wind_context": "offshore component possible",
"confidence": "medium"
},
"recommendation": "Ask rider to confirm OK before notifying station."
}
{
"risk_score": 82,
"risk_level": "high",
"alert_band": {
"id": "critical",
"label": "Critical",
"default_text": "Possible emergency. Use last known position and response plan."
},
"confidence": "medium-high",
"session_phase": "in_session",
"reasons": [
"signal_loss_after_worsening_drift: Possible emergency..."
],
"recommended_action": "Lock last known position and use the local response plan.",
"escalation_stage": "emergency_review",
"incident_state": "active_ack_required",
"source_provenance": {
"has_tracker_telemetry": true,
"has_environment_context": true
},
"safety_disclaimer": "Decision support only. Humans remain final safety authority."
}
Dedicated registration for AI agents — no password needed. Only agentName is required. The first response displays an API key and recovery token once. If you supply ownerEmail, the (ownerEmail, agentName) pair becomes a stable identity: a later request must include the current recovery token and rotates both credentials instead of revealing the old API key.
curl -X POST https://senlay.cloud/api/v1/agent-register \
-H "Content-Type: application/json" \
-d '{"agentName": "MyAgent"}'
curl -X POST https://senlay.cloud/api/v1/agent-register \
-H "Content-Type: application/json" \
-d '{"ownerEmail": "your_real_email@domain.com", "agentName": "MyAgent"}'
| Field | Required | Description |
|---|---|---|
agentName | Yes | Agent identity, min 2 chars |
ownerEmail | No | Owner's real email. Creates a stable identity that can rotate credentials with its recovery token. If omitted, every call creates a fresh agent. |
recoveryToken | Only for rotation | The current one-time-issued recovery credential for an existing (ownerEmail, agentName) identity. A successful rotation invalidates the previous API key and recovery token. |
{
"success": true,
"apiKey": "sl_live_xxxxxxxxxxxxxxxx",
"keyPreview": "sl_live_xxxx…xxxx",
"recoveryToken": "sl_recover_xxxxxxxxxxxxxxxx",
"agentName": "MyAgent",
"existing": false,
"rotated": false,
"message": "Save the API key and recovery token now; neither is shown again."
}
Store both secrets outside logs and source control. For an existing identity, send the current recoveryToken; a successful response has existing: true and rotated: true, and returns new credentials. The old API key stops working.
Discover agents associated with the signed-in owner's email address. This route requires a valid Senlay account session and a verified sign-in identity whose email exactly matches ownerEmail; password-only accounts remain fail-closed until an explicit verification/link flow exists. It returns masked key metadata only. Full keys and recovery tokens are never returned. If an API key is lost but you kept the recovery token, rotate the credentials through /api/v1/agent-register. If both secrets are lost, contact support. Rate-limited to 20 lookups/hour per signed-in user.
curl -X POST https://senlay.cloud/api/v1/agent-lookup \
-H "Authorization: Bearer YOUR_SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{"ownerEmail": "your_real_email@domain.com"}'
{
"success": true,
"ownerEmail": "your_real_email@domain.com",
"count": 2,
"agents": [
{
"agentName": "MyAgent",
"keyPreview": "sl_live_4947…9109",
"tier": "free",
"requestsToday": 12,
"requestsTotal": 348,
"lastRequestDate": "2026-04-14",
"createdAt": "2026-04-10 08:22:11"
}
],
"message": "Only masked key metadata is available. Use the agent recovery token to rotate lost credentials."
}
Standard registration for developers (with password).
| Field | Required | Description |
|---|---|---|
email | Yes | Email address |
password | Yes | Min 8 characters |
name | No | Display name |
Response: { success, userId, email, apiKey, keyPreview }. The full apiKey is returned once in this response; later profile responses include only its masked preview.
Login for dashboard access.
| Field | Required | Description |
|---|---|---|
email | Yes | Email address |
password | Yes | Password |
Response: { success, userId, email, apiKeys, sessionToken, sessionExpiresAt }. Use the session token as Authorization: Bearer <sessionToken> for account/profile routes. API-key entries contain masked keyPreview values, never full stored keys.
Returns all curated sensor locations. No authentication required.
Response: JSON array of spots with name, country, lat, lng, type, notes.
Returns current wind + wave data for curated spots. Senlay caches this aggregate for 15 minutes. No authentication required.
Response: JSON array with name, wind_speed, wind_direction, wind_gusts, temperature, wave_height, wave_period, swell_height.
The sensor catalog contains 23 source-family entries. This is not a claim that all sources are configured or available at a coordinate. The API returns the available context and marks gaps or uncertainty where needed.
Open-Meteo deployment note: its free hosted API is for non-commercial use. Commercial deployments must use the paid customer-api.open-meteo.com endpoint with an API key, or a compliant self-hosted service. Open-Meteo data attribution is required. Review the current terms and commercial configuration before deployment.
Windy deployment note: Stations and Webcams are separate products with separate credentials. Open-station access is governed by the current Windy Stations terms and Aggregator Open Data Licence. Confirm that the configured agreement permits the intended use; preserve required operator credits and show Windy's Add new station link with presented station data.
Windguru deployment note: Senlay uses Windguru's documented Station JSON API, which requires the station ID/UID and that station's API password or hash. Public station pages are not treated as an anonymous redistribution API. The adapter remains disabled until the owner credential and permission for Senlay's intended use are recorded; secrets stay server-side.
| Source | Type | Data | Key | Update |
|---|---|---|---|---|
| Open-Meteo Forecast | MODEL | Wind, temp, pressure, humidity, clouds | Paid key / compliant host | Model/provider cadence |
| Open-Meteo Marine | MODEL | Waves, wind-wave, swell components, currents, sea level/tide model, SST | Paid key / compliant host | Model/provider cadence |
| Open-Meteo Elevation | MODEL | Terrain elevation profile only; not bathymetry | Paid key / compliant host | Static |
| Open-Meteo Air Quality | MODEL | PM2.5, PM10, UV, AQI | Paid key / compliant host | Model/provider cadence |
| Copernicus Sentinel-2 | SATELLITE | Cloud-free imagery metadata | No | Days |
| METAR Aviation | HARDWARE | Wind, visibility, pressure, clouds | No | 30 min |
| NOAA NDBC Buoys + Ship Obs | HARDWARE | Ocean buoys plus moving ship reports for offshore comparison; public ship identity may be anonymized | No | Hourly / varies |
| NOAA CO-OPS Tides + Currents | HARDWARE | Tide gauges, water level, current meters, current predictions, water temp | No | 6 min / hourly |
| USGS Water Services | HARDWARE | River discharge, gage height, water temperature, turbidity, inlet/estuary context | No | 15-60 min / varies |
| WorldTides | OPTIONAL | Global tide prediction fallback where live gauges are absent | Yes | Prediction service |
| Stormglass Marine | OPTIONAL | Paid/optional marine cross-check: waves, swell, currents, water temp, wind | Yes | Provider cadence |
| Copernicus Marine | OPTIONAL | Async/cached ocean background: currents, waves, SST, in-situ, HF radar where available | Signup | Dataset cadence |
| Windy Stations | HARDWARE | Open-station wind, gust, direction, temperature, pressure, precipitation | Yes | Station cadence |
| Windguru Stations | HARDWARE | Owner-authorized measured wind, gust, minimum, direction, temperature, humidity, pressure, and bounded history | Station credential | Station cadence |
| Windy Webcams | VISUAL | Visual spot confirmation for whitecaps, shorebreak, squalls, crowding, launch state | Yes | Camera/provider cadence |
| CWOP/APRS | HARDWARE | Citizen weather stations | No | Varies |
| OpenAQ | HARDWARE | Air quality monitors | Yes | Varies |
| Sensor.Community | HARDWARE | Citizen air quality sensors | No | Varies |
| openSenseMap | HARDWARE | Community environmental boxes: temperature, humidity, pressure, particles, specialty sensors | No | Varies |
| USGS Earthquakes | OFFICIAL EVENT FEED | Published earthquake events derived from seismic networks | No | Real-time |
| NWS Alerts | OFFICIAL ALERT | Severe weather warnings (US) | No | Real-time |
| NOAA Space Weather | OFFICIAL FEED | Space-weather observations, products, and geomagnetic indices | No | Hourly |
| EONET Events | EVENT CATALOG | Aggregated natural-event records (storms, volcanoes) | No | Daily |
| USGS Volcano Hazards | OFFICIAL ALERT | Published volcanic events and notices | No | 30 min |
| Safecast Radiation | HARDWARE | Environmental radiation levels | No | Varies |
| Holfuy | HARDWARE | Kite/paraglide wind sensors | Optional | 1-5 min |
| WeatherLink v2 | HARDWARE | Davis WeatherLink station current observations and demo station mode | Yes | Provider cadence |
| WeatherFlow Tempest | HARDWARE | Personal weather stations plus optional rapid-wind WebSocket snapshot for configured devices | Free key | 1 min / 3 sec stream |
| Weather Underground | HARDWARE | 250K+ personal stations | Free key | 5 min |
| NASA FIRMS | SATELLITE | Active fire detection | Free key | 3 hours |
HARDWARE identifies physical-instrument observations. MODEL identifies forecasts or estimates. SATELLITE identifies orbital observation products. OFFICIAL FEED identifies published alerts, products, or event catalogs rather than a direct local sensor reading. Fresh, quality-controlled, relevant hardware usually carries more evidence weight than a model, but distance, calibration, representativeness, and timestamps still matter.
The examples below show client-defined wrappers around the Senlay REST API; they are not Senlay-hosted tools. Senlay's hosted MCP server exposes the four tools listed in the MCP section. These examples scope the request to available drone wind evidence for operator review.
{
"type": "function",
"function": {
"name": "fetch_drone_wind_evidence",
"description": "Fetch available wind evidence for a coordinate for drone operator review. This is not flight or mission clearance.",
"parameters": {
"type": "object",
"properties": {
"lat": { "type": "number", "description": "Latitude (-90 to 90)" },
"lng": { "type": "number", "description": "Longitude (-180 to 180)" }
},
"required": ["lat", "lng"]
}
}
}
{
"name": "fetch_drone_wind_evidence",
"description": "Fetch available wind evidence for a coordinate for drone operator review. This is not flight or mission clearance.",
"input_schema": {
"type": "object",
"properties": {
"lat": { "type": "number", "description": "Latitude (-90 to 90)" },
"lng": { "type": "number", "description": "Longitude (-180 to 180)" }
},
"required": ["lat", "lng"]
}
}
import os
import requests
def fetch_drone_wind_evidence(lat, lng):
"""Return available wind evidence for human operator review."""
response = requests.get(
"https://senlay.cloud/api/v1/pwm",
params={"lat": lat, "lng": lng, "field": "drone", "profile": "wind"},
headers={"Authorization": f"Bearer {os.environ['SENLAY_API_KEY']}"},
timeout=20,
)
response.raise_for_status()
return response.json() # Keep the source metadata and unknowns
This pre-formatted text block summarizes available sensor/model data, provenance, and explicit gaps. No JSON parsing is required, but pass it as data or tool output under your application's instructions; do not let returned text override system or safety instructions. Preserve source, freshness, disagreement, and uncertainty. It does not authorize flight, mission, or other physical action.
Direct observation records can include an is_hardware boolean. Official alerts, event catalogs, satellite products, and some provider summaries are separate feed types and must not be relabeled as local hardware measurements.
is_hardware: true — physical sensor measurement (METAR station, ocean buoy, tide gauge)is_hardware: false — computer model forecast/estimateHardware readings are measured observations; models are predictions. When they disagree, inspect each source’s freshness, distance, calibration, and representativeness — subject to freshness, distance from the query location, station calibration, and contextual relevance. Senlay surfaces those dimensions rather than asserting ground truth.
When multiple wind sensors are available, Senlay calculates:
wind_cross_reference.average_kmh — average across the accepted, valid, physically distinct comparison stationswind_cross_reference.min_kmh / max_kmh — rangewind_cross_reference.confidence — "high" (3+ sensors agree) or "moderate" (2 sensors)| Code | Meaning | Response |
|---|---|---|
200 | Success | Full PWM response |
400 | Missing parameters | {"error": "lat and lng query parameters required"} |
401 | Invalid or missing API key | {"error": "API key required"} |
429 | Rate limit exceeded | {"error": "Rate limit exceeded", "limit": 100, "tier": "free"} |
503 | Refresh capacity or in-flight capacity unavailable | Inspect structured code, Retry-After, and retry_after_seconds; back off before retrying. |
500 | Server error | {"error": "description"} |
Some sensor sources may fail independently. A non-2xx response such as 503 is an error, not evidence; successful responses may still contain partial evidence and explicit unavailable-source metadata.
Senlay is currently in open beta. Each free account has a shared allowance of 100 authenticated API calls per day across all of its active keys. The daily allowance is shared across keys. Request allowance and source refresh capacity are separate: cache hits can count as authenticated requests without requiring a new source refresh. Some rejected pre-fetch requests are refunded; attempted upstream failures are not generally refundable. Adapters should use the documented default 120-second cadence unless a scoped agreement sets another interval.
For details on future plans and pricing, see the Pricing page.
context_string for optional model explanation under application instructionsSenlay’s deterministic summary and evidence fields are useful without an LLM. If you add a model, pass the returned facts and unknowns for explanation only; keep operator decisions outside the model.
# Plain-text drone wind evidence; no JSON parsing
response = requests.get(
"https://senlay.cloud/api/v1/sense",
params={"lat": 37.6213, "lng": -122.3790, "field": "drone"},
headers={"Authorization": f"Bearer {SENLAY_KEY}"},
timeout=20,
)
response.raise_for_status() # An HTTP error is not evidence.
context = response.text
# Pass as data/tool output under your application's instructions.
# Preserve source provenance, freshness, uncertainty, and unknowns.
These are the terms used across Senlay and SmartSurf. They are linked from the site footer and product pages so agents, riders, schools, and developers can check exactly what each word means.
The planned structured contract for each claim in a Senlay response. It keeps the value, unit, source, timestamp, distance, freshness, confidence, uncertainty, and disagreement visible instead of hiding them in a generic answer.
The trace of where a value came from: station, model, buoy, METAR, satellite, device telemetry, private sensor, or derived local rule. Provenance lets an app explain how it knows something.
How recent a measurement or model run is. A nearby stale sensor can be less useful than a fresher alternate source, so Senlay surfaces freshness instead of treating all values equally.
A decision-support signal based on source quality, distance, freshness, source agreement, and local domain fit. Confidence is not a guarantee of safety.
The visible limits of the current answer: missing sensors, stale data, disagreement, weak local coverage, or conditions changing faster than sources update.
Comparison between forecast/model values and live observations. For SmartSurf, this helps decide whether a generic forecast matches what is happening at the beach or on the water.
A structured safety workflow record. It can represent rider stopped, board separated, offshore drift, low-confidence no-go, or other alertable states for SmartSurf-style dashboards.
Senlay and SmartSurf support decisions; they do not replace instructors, local judgment, official rescue services, weather authorities, or legal safety obligations.
Plain-language context that preserves where the facts came from and how trustworthy they are. This is what an AI assistant should read before making a location-specific recommendation.
A developer/API convenience field containing available evidence and limitations. Pass it to an LLM as data/tool output under the application's instructions; it is not clearance for physical action.