Kotlin Coroutines + Retrofit + OkHttp v1.0.0

Weather Data for Your
Kotlin Apps, Simplified

A developer-friendly SDK for the National Weather Service API. Forecasts, alerts, observations, and glossary with clean Kotlin types and coroutine-first design.

No API Key Required Kotlin 1.9+ / Java 11+ Open Source

Everything You Need from the NWS API

Four complete service layers covering all major NWS endpoints, with clean models and structured error handling.

Forecasts

Daily and hourly forecasts by coordinates, gridpoint, or zone. Automatic lat/lon to gridpoint resolution.

Alerts

Active weather alerts filtered by state, zone, or ID. Typed severity, urgency, and certainty enums.

Observations

Current conditions from weather stations. Temperature, humidity, wind, pressure, visibility, and more.

Coroutine-First

All service methods are suspend functions. Clean, non-blocking async with Retrofit's native support.

Structured Errors

Typed exception hierarchy for API errors, rate limits, network failures, and parse errors.

SLF4J Logging

Built-in structured logging via SLF4J. Debug, info, and error logs across all services. Plug any backend.

Up and Running in 30 Seconds

Add the dependency, create the SDK, start fetching weather data. No API keys, no complex setup.

build.gradle.kts
// Add to your dependencies block
implementation("dev.abid.noaa.weather:noaa-weather-sdk-kotlin:1.0.0")

// SLF4J backend of your choice (e.g., Logback)
runtimeOnly("ch.qos.logback:logback-classic:1.5.6")
Main.kt
import dev.abid.noaa.weather.sdk.NoaaWeatherSdk
import kotlinx.coroutines.runBlocking

fun main() = runBlocking {
    val sdk = NoaaWeatherSdk.builder()
        .userAgent("my-weather-app, contact@example.com")
        .build()

    val forecast = sdk.forecasts.getDailyForecast(39.7456, -104.9984)
    forecast.periods.forEach { period ->
        println("${period.name}: ${period.temperature}${period.temperatureUnit}")
    }
}

Complete API Reference

Everything you need to integrate weather data into your Kotlin application.

Configuration NoaaWeatherConfig

The SDK is configured via the builder pattern. The userAgent field is required by the NWS API — use the format "app-name, contact-info".

userAgent
String (required)
App identifier sent in the User-Agent header. Required by NWS.
baseUrl
String
API base URL. Default: https://api.weather.gov. Override for testing.
connectTimeout
Duration
HTTP connection timeout. Default: 10 seconds.
readTimeout
Duration
HTTP read timeout. Default: 30 seconds.
enableLogging
Boolean
Enable OkHttp HTTP request/response logging. Default: false.

ForecastService sdk.forecasts

Fetch daily and hourly forecasts. Methods that take coordinates automatically resolve to the nearest gridpoint via the NWS /points endpoint.

MethodReturnsDescription
getDailyForecast(lat, lon)DailyForecastDaily forecast for coordinates. Auto-resolves gridpoint.
getHourlyForecast(lat, lon)List<HourlyForecast>Hourly forecast for coordinates.
getGridpointForecast(wfo, x, y)GridpointForecastDaily forecast by gridpoint (skip location lookup).
getGridpointHourly(wfo, x, y)List<HourlyForecast>Hourly forecast by gridpoint.
getZoneForecast(zoneId)ZoneForecastForecast by NWS zone ID (e.g., "COZ001").
ForecastPeriod

name, startTime, endTime, temperature, temperatureUnit, windSpeed, windDirection, shortForecast, detailedForecast, icon

HourlyForecast

time, temperature, dewpoint, relativeHumidity, probabilityOfPrecipitation, windChill, heatIndex

DailyForecast

periods: List<ForecastPeriod>, generatedAt: Instant

GridPoint

wfo: String (e.g., "BOU"), gridX: Int, gridY: Int

AlertService sdk.alerts

Query active weather alerts. Alerts include typed enums for severity, urgency, and certainty — no string parsing needed.

MethodReturnsDescription
getActiveAlerts()List<Alert>All currently active alerts.
getAlertsByArea(stateCode)List<Alert>Alerts for a 2-letter US state code (e.g., "CO").
getAlertsByZone(zoneId)List<Alert>Alerts for an NWS zone (e.g., "COZ001").
getAlert(id)AlertSingle alert by its NWS identifier.
Alert

id, event, headline, description, instruction, area, affectedZones, effective, expires, sender

AlertSeverity

EXTREME, SEVERE, MODERATE, MINOR, UNKNOWN

AlertUrgency

IMMEDIATE, EXPECTED, FUTURE, PAST, UNKNOWN

AlertCertainty

OBSERVED, LIKELY, POSSIBLE, UNLIKELY, UNKNOWN

ObservationService sdk.observations

Access current conditions from NWS observation stations. Find stations by location, then retrieve the latest readings.

MethodReturnsDescription
getNearbyStations(lat, lon)List<Station>Observation stations near the given coordinates.
getLatestObservation(stationId)ObservationMost recent reading from a station (e.g., "KDEN").
getObservations(stationId)List<Observation>Historical observations from a station.
Station

id, name, coordinates: GeoPoint, elevation

Observation

temperature, dewpoint, windSpeed, windDirection, windGust, barometricPressure, visibility, relativeHumidity, precipitationLastHour, weatherDescription

GlossaryService sdk.glossary

NWS term definitions and weather icon metadata. Useful for building educational or reference interfaces.

All NWS glossary terms and definitions.

MethodReturnsDescription
getGlossaryTerms()List<GlossaryTerm>
getIcons()List<IconInfo>Weather icon metadata from the NWS icon library.

Logging SLF4J

The SDK uses SLF4J for structured logging. Add your preferred backend (Logback, Log4j2, SLF4J-Simple) and everything lights up automatically. No implementation binding is included — that's the consumer's choice.

ComponentDEBUGINFOERROR
InterceptorEvery request URL + response codeRate limits (429), API errors
ForecastServiceLat/lon params, gridpoint paramsResolved gridpoint, period count
AlertServiceState/zone/id paramsAlert count, event details
ObservationServiceStation ID, coordinatesStation count, temp summary
GlossaryServiceEndpoint being calledTerm/icon countParse failures (with stack trace)
logback.xml
<!-- Enable SDK debug logs -->
<logger name="dev.abid.noaa.weather.sdk" level="DEBUG"/>

Service Usage

Each service is a property on the SDK instance. All methods are coroutine suspend functions.

Forecasts
// Hourly forecast by coordinates
val hourly = sdk.forecasts
    .getHourlyForecast(39.7456, -104.9984)

// Direct gridpoint (skip lookup)
val grid = sdk.forecasts
    .getGridpointForecast("BOU", 65, 61)

// Zone-based forecast
val zone = sdk.forecasts
    .getZoneForecast("COZ001")
Alerts
// All active alerts
val all = sdk.alerts.getActiveAlerts()

// By state (2-letter code)
val co = sdk.alerts
    .getAlertsByArea("CO")

// Single alert
val alert = sdk.alerts
    .getAlert("urn:oid:2.49.0...")
println(alert.severity) // EXTREME
Observations
// Find nearby stations
val stations = sdk.observations
    .getNearbyStations(39.86, -104.67)

// Latest reading
val obs = sdk.observations
    .getLatestObservation("KDEN")
println("Temp: ${obs.temperature}")
println("Wind: ${obs.windSpeed}")
Configuration
val sdk = NoaaWeatherSdk.builder()
    .userAgent("my-app, me@example.com")
    .baseUrl("http://localhost:8080")
    .connectTimeout(5.seconds)
    .readTimeout(15.seconds)
    .enableLogging(true)
    .build()

Typed Exceptions for Every Scenario

All errors are subclasses of NoaaWeatherException, making catch blocks clean and specific.

ExceptionWhenKey Properties
NoaaApiExceptionNWS API returned a non-2xx responsestatusCode, errorBody
NoaaRateLimitExceptionHTTP 429 — too many requestsretryAfter
NoaaNetworkExceptionNetwork failure (timeout, DNS, etc.)cause (IOException)
NoaaParseExceptionResponse body could not be parsedrawBody
Error Handling
try {
    val forecast = sdk.forecasts.getDailyForecast(39.7456, -104.9984)
} catch (e: NoaaRateLimitException) {
    println("Rate limited. Retry after: ${e.retryAfter}")
} catch (e: NoaaApiException) {
    println("API error ${e.statusCode}: ${e.message}")
} catch (e: NoaaNetworkException) {
    println("Network error: ${e.message}")
} catch (e: NoaaWeatherException) {
    println("SDK error: ${e.message}")
}

Ready to Build with Weather Data?

Start fetching forecasts, alerts, and observations in your Kotlin app today. Free, open-source, no API key needed.

Get Started Now