Overview

Senlay is a spot-level verification API for SmartSurf, outdoor AI apps, IoT products, and safety applications. It is not a weather API wrapper: each response is built to explain what is happening at a coordinate, which sources support it, how fresh they are, whether they disagree, and what the decision context means.

The Physical World Model (PWM) is a real-time, multi-layered representation of physical conditions at a coordinate. One verification request can combine available data from 21 source families — including hardware weather stations, ocean buoys, tide gauges, seismometers, models, and satellites — into a unified response your AI can immediately use.

For developer workflows, the response can include a pre-formatted context_string ready to inject into an LLM context. For safety workflows such as SmartSurf, Senlay can also produce risk_event records that turn physical evidence into 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 gives hardware a higher evidence weight — while still exposing freshness, distance to the source, data quality, and uncertainty so your agent can reason about how much to trust any single value.

Direct answers for agents and developers

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.
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?Inject it before answering, cite source/freshness/confidence, and present decision support rather than guaranteed safety.

Provenance & Evidence

Every PWM response carries source-and-freshness metadata so your agent knows how it knows. The platform is moving toward a fully structured Senlay Evidence Object per claim — this is the shape to expect:

JSON — Evidence Object (target shape)
{
  "claim": "Wave height is 0.7 m",
  "value": 0.7,
  "unit": "m",
  "evidence_type": "measured_telemetry",
  "source": {
    "type": "buoy",
    "id": "KLIH1",
    "distance_km": 18,
    "timestamp": "2026-04-18T11:48:00Z"
  },
  "freshness": "recent",
  "confidence": "medium_high",
  "model_disagreement": {
    "forecast_value": 0.5,
    "difference": 0.2
  },
  "interpretation": "Small but measurable swell; suitable for low-risk coastal activity.",
  "uncertainty": "Nearest buoy is 18 km away; local break conditions may vary."
}

Today this metadata is exposed across current_source, source_use, per-layer source labels, interaction/domain modifiers, decision context, and the context_string. Confidence scoring, freshness decay, and explicit disagreement flags are landing as part of Evidence Object v1.

Evidence-shaped context_string

The pre-formatted context_string reads like provenance-aware prose, ready to inject into any LLM:

Example context_string
Current Maui ocean state: 0.7 m waves measured by NDBC buoy KLIH1
18 km away, updated 12 minutes ago. Confidence medium-high.
Forecast underestimates the live measurement by 0.2 m — treat
conditions as building. Local break conditions may vary by exposure.

Authentication

Production endpoints require a Bearer token. The public /api/v1/try-sense endpoint is a limited no-key trial for browser-based chat agents.

HTTP Header
Authorization: Bearer sl_live_your_key_here

Start with pricing: senlay.world/pricing - then create a free key, no credit card.

Quick Start

For a chat model that can browse but cannot send POST bodies or Bearer headers, use the no-key trial URL:

Plain URL
https://senlay.world/api/v1/try-sense?lat=15.8801&lng=108.3380&field=kitesurfing&agentName=ChatGPT_Test_Agent

For a self-updating browser view of the same request, open the live page URL:

Live Page
https://senlay.world/agents/live?lat=15.8801&lng=108.3380&field=kitesurfing&agentName=ChatGPT_Test_Agent&request=Can%20I%20kite%20safely%20now%3F

For production agents, create a free key and call the authenticated API:

curl
curl -H "Authorization: Bearer sl_live_your_key" \
  "https://senlay.world/api/v1/pwm?lat=36.01&lng=-5.60&field=drone"

For plain text output (no JSON parsing needed):

curl
curl -H "Authorization: Bearer sl_live_your_key" \
  "https://senlay.world/api/v1/sense?lat=36.01&lng=-5.60&field=drone"

GET /api/v1/try-sense

Public, no-key trial endpoint for chat agents with browsing. It returns plain text, includes instructions for the model, and is rate-limited. Use this when a user wants to paste one URL into ChatGPT, Claude, Gemini, or another agent and immediately ground the conversation in live physical context.

GET URL
https://senlay.world/api/v1/try-sense?lat=36.01&lng=-5.60&field=drone&agentName=MyChatAgent

Parameters

ParameterRequiredDescription
latYesLatitude (-90 to 90)
lngYesLongitude (-180 to 180)
fieldNoReasoning mode, for example kitesurfing, drone, sailing, agriculture, running, or general
agentNameNoHuman-readable name shown in the trial response
requestNoAgent/user task embedded into the response so the model can answer with the correct field context
viewNoUse 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.

GET /api/v1/pwm

Full Physical World Model — structured JSON with all sensor data, extended hardware readings, satellite data, and the pre-formatted context string.

Parameters

ParameterRequiredDescription
latYesLatitude (-90 to 90)
lngYesLongitude (-180 to 180)
fieldNoOptional reasoning mode used when building context_string

Response

JSON Response
{
  "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": -6, "is_ocean": true,
        "depth_profile": [-4, -6, -8, -12, -6, -3, -6, -8, -10]
      },
      "air_quality": {
        "current": {
          "pm2_5": 12.3, "pm10": 18.7,
          "uv_index": 6.2, "european_aqi": 42
        }
      }
    }
  },
  "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 === ..."
}

Response Fields

FieldTypeDescription
statusstring"ok" on success
active_sourcesnumberCount of sensor sources that returned data
pwmobjectRaw sensor data with all layers (atmosphere, hydrosphere, terrain, air quality)
extendedobjectHardware sensor data (METAR, buoys, tides, seismic, fires, space weather)
satelliteobjectSentinel-2 imagery metadata
healtharrayPer-source latency and status report
context_stringstringPre-formatted text for LLM injection — the most important field

GET /api/v1/sense

Simplified endpoint — returns only the context_string as plain text. Content-Type: text/plain. Ideal for agents that don't want to parse JSON.

Parameters

Same as /api/v1/pwm: lat (required), lng (required), and optional field for the reasoning mode.

curl
curl -H "Authorization: Bearer sl_live_your_key" \
  "https://senlay.world/api/v1/sense?lat=36.01&lng=-5.60&field=drone"

Returns the full Physical World Model as a plain text block. No parsing needed — inject it into your agent so it can reason from current physical context.

GET /api/v1/risk-events

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.

Related endpoints

EndpointUse
GET /api/v1/risk-eventsCurrent active operational risk events.
POST /api/v1/risk-eventsCreate or submit a risk event from an application workflow.
GET /api/v1/risk-events/recentRecent persisted events for audit, review, and station logs.
curl
curl -H "Authorization: Bearer sl_live_your_key" \
  "https://senlay.world/api/v1/risk-events?status=active"

Risk event shape

Example JSON
{
  "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."
}

POST /api/v1/agent-register

Dedicated registration for AI agents — no password needed. Only agentName is required. If you supply ownerEmail too, we dedupe on the (ownerEmail, agentName) pair so stateless agents that re-register each session get the SAME key back instead of piling up orphan rows.

curl — minimum
curl -X POST https://senlay.world/api/v1/agent-register \
  -H "Content-Type: application/json" \
  -d '{"agentName": "MyAgent"}'
curl — recommended (stable key across sessions)
curl -X POST https://senlay.world/api/v1/agent-register \
  -H "Content-Type: application/json" \
  -d '{"ownerEmail": "your_real_email@domain.com", "agentName": "MyAgent"}'

Request Body

FieldRequiredDescription
agentNameYesAgent identity, min 2 chars
ownerEmailNoOwner's real email. Enables dedupe on re-register. If omitted, every call creates a fresh key.

Response

JSON
{
  "success": true,
  "apiKey": "sl_live_xxxxxxxxxxxxxxxx",
  "agentName": "MyAgent",
  "existing": false,
  "message": "Save your API key — it cannot be recovered."
}

If existing is true, we returned a previously-issued key because (ownerEmail, agentName) was already registered.

POST /api/v1/agent-lookup

Discover what agents you've registered under an email address. Returns agent names with masked key previews only (first 12 + last 4 chars). Full keys are never returned by this endpoint. To recover the full key, call /api/v1/agent-register again with the same (ownerEmail, agentName) — dedupe returns the original key. Rate-limited 10/hour per email.

curl
curl -X POST https://senlay.world/api/v1/agent-lookup \
  -H "Content-Type: application/json" \
  -d '{"ownerEmail": "your_real_email@domain.com"}'

Response

JSON
{
  "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": "To get the full key for an agent, POST /api/v1/agent-register with the same ownerEmail + agentName."
}

POST /api/register

Standard registration for developers (with password).

FieldRequiredDescription
emailYesEmail address
passwordYesMin 8 characters
nameNoDisplay name

Response: { success, apiKey }

POST /api/login

Login for dashboard access.

FieldRequiredDescription
emailYesEmail address
passwordYesPassword

Response: { success, userId, apiKeys }

GET /api/spots

Returns all curated sensor locations. No authentication required.

Response: JSON array of spots with name, country, lat, lng, type, notes.

GET /api/conditions

Returns current wind + wave data for curated spots. Cached 30 minutes. No authentication required.

Response: JSON array with name, wind_speed, wind_direction, wind_gusts, temperature, wave_height, wave_period, swell_height.

Data Sources

Senlay can aggregate data from 21 source families where available. Not all sources have data at every location — coastal areas have the most hardware sensors. The API returns the available context and marks gaps or uncertainty where needed.

SourceTypeDataKeyUpdate
Open-Meteo ForecastMODELWind, temp, pressure, humidity, cloudsNo15 min
Open-Meteo MarineMODELWaves, wind-wave, swell components, currents, sea level/tide model, SSTNo15 min / model cadence
Open-Meteo ElevationMODELTerrain, bathymetry, depth profileNoStatic
Open-Meteo Air QualityMODELPM2.5, PM10, UV, AQINo15 min
Copernicus Sentinel-2SATELLITECloud-free imagery metadataNoDays
METAR AviationHARDWAREWind, visibility, pressure, cloudsNo30 min
NOAA NDBC Buoys + Ship ObsHARDWAREOcean buoys plus moving ship reports for offshore comparison; public ship identity may be anonymizedNoHourly / varies
NOAA CO-OPS Tides + CurrentsHARDWARETide gauges, water level, current meters, current predictions, water tempNo6 min / hourly
USGS Water ServicesHARDWARERiver discharge, gage height, water temperature, turbidity, inlet/estuary contextNo15-60 min / varies
WorldTidesOPTIONALGlobal tide prediction fallback where live gauges are absentYesPrediction service
Stormglass MarineOPTIONALPaid/optional marine cross-check: waves, swell, currents, water temp, windYesProvider cadence
Copernicus MarineOPTIONALAsync/cached ocean background: currents, waves, SST, in-situ, HF radar where availableSignupDataset cadence
Windy WebcamsVISUALVisual spot confirmation for whitecaps, shorebreak, squalls, crowding, launch stateYesCamera/provider cadence
CWOP/APRSHARDWARECitizen weather stationsNoVaries
OpenAQHARDWAREAir quality monitorsNoVaries
Sensor.CommunityHARDWARECitizen air quality sensorsNoVaries
openSenseMapHARDWARECommunity environmental boxes: temperature, humidity, pressure, particles, specialty sensorsNoVaries
USGS EarthquakesHARDWARESeismic activityNoReal-time
NWS AlertsHARDWARESevere weather warnings (US)NoReal-time
NOAA Space WeatherHARDWARESolar storms, geomagnetic indicesNoHourly
EONET EventsSATELLITENatural events (storms, volcanoes)NoDaily
USGS Volcano HazardsHARDWAREActive volcanic eventsNo30 min
Safecast RadiationHARDWAREEnvironmental radiation levelsNoVaries
HolfuyHARDWAREKite/paraglide wind sensorsOptional1-5 min
WeatherLink v2HARDWAREDavis WeatherLink station current observations and demo station modeYesProvider cadence
WeatherFlow TempestHARDWAREPersonal weather stations plus optional rapid-wind WebSocket snapshot for configured devicesFree key1 min / 3 sec stream
Weather UndergroundHARDWARE250K+ personal stationsFree key5 min
NASA FIRMSSATELLITEActive fire detectionFree key3 hours

HARDWARE sources are real physical instruments measuring reality. MODEL sources are computer forecasts. SATELLITE sources are orbital observation data. When hardware and models disagree, trust HARDWARE.

Agentic Tooling

Use Senlay as a function/tool in AI agent frameworks. Let the AI decide when it needs physical world data.

OpenAI Function Definition

JSON
{
  "type": "function",
  "function": {
    "name": "sense_physical_world",
    "description": "Get real-time physical world data for a coordinate. Returns available atmosphere, ocean, terrain, air quality, live hardware sensors, earthquakes, fires, and satellite context from 21 source families where available.",
    "parameters": {
      "type": "object",
      "properties": {
        "lat": { "type": "number", "description": "Latitude (-90 to 90)" },
        "lng": { "type": "number", "description": "Longitude (-180 to 180)" }
      },
      "required": ["lat", "lng"]
    }
  }
}

Claude Tool Definition

JSON
{
  "name": "sense_physical_world",
  "description": "Perceive available real-time physical conditions at a coordinate from 21 source families including hardware weather stations, ocean buoys, tide gauges, seismometers, and satellites.",
  "input_schema": {
    "type": "object",
    "properties": {
      "lat": { "type": "number", "description": "Latitude (-90 to 90)" },
      "lng": { "type": "number", "description": "Longitude (-180 to 180)" }
    },
    "required": ["lat", "lng"]
  }
}

Implementation Example

Python
def sense_physical_world(lat, lng):
    """Call this when your AI needs to evaluate physical conditions."""
    response = requests.get(
        "https://senlay.world/api/v1/sense",
        params={"lat": lat, "lng": lng},
        headers={"Authorization": f"Bearer {SENLAY_KEY}"}
    )
    return response.text  # Ready to inject into context

Understanding the PWM

The context_string

The most important field in the response. It's a pre-formatted text block designed to be injected directly into any LLM's system prompt or user message. Contains all sensor data in natural language that AI can immediately understand and reason about. No parsing required.

HARDWARE vs MODEL

Every data point in the extended response has an is_hardware boolean.

Hardware readings are measured observations; models are predictions. When they disagree, the hardware value generally carries more weight — subject to freshness, distance from the query location, station calibration, and contextual relevance. Senlay surfaces those dimensions rather than asserting ground truth.

Cross-referencing

When multiple wind sensors are available, Senlay calculates:

Error Handling

CodeMeaningResponse
200SuccessFull PWM response
400Missing parameters{"error": "lat and lng query parameters required"}
401Invalid or missing API key{"error": "API key required"}
429Rate limit exceeded{"error": "Rate limit exceeded", "limit": 100, "tier": "free"}
500Server error{"error": "description"}

Some sensor sources may fail independently — the API still returns successfully with whatever data is available. Check active_sources to see how many sources responded.

Rate Limits

Senlay is currently in open beta — all features are free to use. The free tier includes 100 API calls per day. Cached responses for the same location within 5 minutes don't count against your limit.

For details on future plans and pricing, see the Pricing page.

What's included in every request

Code Examples

Python + Claude

Python
import anthropic, requests

pwm = requests.get(
    "https://senlay.world/api/v1/pwm",
    params={"lat": 36.01, "lng": -5.60},
    headers={"Authorization": "Bearer sl_live_your_key"}
).json()

client = anthropic.Anthropic()
response = client.messages.create(
    model="claude-sonnet-4-20250514",
    system=f"Use this current spot-level verification:\n\n{pwm['context_string']}",
    messages=[{"role": "user", "content": "Is it safe to fly a drone here?"}]
)

Python + OpenAI

Python
from openai import OpenAI
import requests

pwm = requests.get(
    "https://senlay.world/api/v1/pwm",
    params={"lat": 36.01, "lng": -5.60},
    headers={"Authorization": "Bearer sl_live_your_key"}
).json()

client = OpenAI()
response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": pwm["context_string"]},
        {"role": "user", "content": "Should I irrigate today?"}
    ]
)

JavaScript

JavaScript
const res = await fetch(
  "https://senlay.world/api/v1/pwm?lat=36.01&lng=-5.60",
  { headers: { Authorization: "Bearer sl_live_your_key" } }
);
const pwm = await res.json();

// Inject into ANY LLM system prompt:
const systemPrompt = `Physical World Model:\n\n${pwm.context_string}`;

// Works with Claude, GPT, Gemini, Llama, Mistral, Cohere...

Plain text with /sense

Python
# Simplest possible integration — no JSON parsing
context = requests.get(
    "https://senlay.world/api/v1/sense",
    params={"lat": 36.01, "lng": -5.60},
    headers={"Authorization": f"Bearer {SENLAY_KEY}"}
).text

# context is ready to inject directly into any LLM
Get Your API Key

Verification Glossary

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.

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.

Source provenance

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.

Freshness

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.

Confidence

A decision-support signal based on source quality, distance, freshness, source agreement, and local domain fit. Confidence is not a guarantee of safety.

Uncertainty

The visible limits of the current answer: missing sensors, stale data, disagreement, weak local coverage, or conditions changing faster than sources update.

Model-vs-reality check

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.

risk_event

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.

Decision-support boundary

Senlay and SmartSurf support decisions; they do not replace instructors, local judgment, official rescue services, weather authorities, or legal safety obligations.

Source-aware context

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.

context_string

A developer/API convenience field that can be injected into an LLM prompt. It belongs in docs and integrations, not as the main marketing promise.