Webhooks
WindBorne webhooks let you receive real-time HTTP POST notifications as forecast outputs become available. Instead of polling the API, register a webhook URL and configure the subscriptions you care about.
How It Works
- You register a webhook with a target URL and one or more subscriptions via POST /webhooks/v1 .
- When a subscription matches, WindBorne sends an HTTP POST to your URL with a JSON payload.
- Your server responds with a 2xx status to acknowledge receipt.
- Failed deliveries are retried with exponential backoff.
Subscription Types
| Subscription | Category | Description |
|---|---|---|
| initialization_time.available | Forecasts | Sent once every expected forecast hour for a model run is available |
| forecast_hour.available | Forecasts | Sent as each individual forecast output becomes available |
| degree_days.available | Forecasts | Sent when a degree day calculation becomes available for a model run |
| tropical_cyclones.available | Forecasts | Sent when a tropical cyclone calculation becomes available; payloads include data.tropical_cyclone_ids |
Quick Start
Create a webhook that subscribes to completed WM6 forecast cycles:
Filtering by Initialization and Valid Time
All subscription types support initialization_time_hours , which compares the UTC hour and minute of an event's initialization time. Values accept H:MM or HH:MM ; seconds are ignored.
Use inclusive ISO 8601 min_initialization_time and max_initialization_time bounds to match the event's run initialization timestamp.
All types also support inclusive ISO 8601 min_valid_at and max_valid_at bounds. Forecast-hour events compare their valid_at ; initialization-time, degree-day, and tropical-cyclone events match when the source model run's forecast range covers the configured bounds.
List filters accept a scalar or an array. An array matches any listed value, while different filters combine with AND semantics. Arrays are not paired by position: a model array and an initialization-time array match every combination. Degree-day subscriptions accept any model with degree-day calculations enabled. Tropical-cyclone subscriptions currently accept only wm-6 . When a model filter is omitted, the subscription can match any model supported by that calculation type. Minimum and maximum time bounds accept one ISO 8601 timestamp each.
A webhook can contain at most one subscription of each type. For subscriptions that accept a model filter, create separate webhooks when different models need different initialization-time schedules rather than trying to pair entries within the filter arrays.
Attaching Forecast Responses
An optional response_options object enriches a matching event with forecast data. Depending on its type, a subscription can select gridded , interpolated_point_forecast , tropical_cyclones , or degree_days .
WindBorne derives the model, initialization time, and applicable forecast hour from the trigger, then places the selected enrichment in data.response . The calculation subscriptions only support their paired response options: tropical_cyclones.available uses tropical_cyclones , and degree_days.available uses degree_days . These response options inherit system event metadata and do not accept a model; select models with the subscription filter instead. For forecast_hour.available , an interpolated point forecast calls the endpoint with the triggering forecast hour as its inclusive cutoff, so the complete endpoint response contains the series from the start of the run through that hour. Every tropical_cyclones.available event includes the unique tropical cyclone IDs in data.tropical_cyclone_ids , even without a response option. Tropical cyclone enrichment adds time-limited URLs for those IDs; its basin option narrows only the attached URLs and does not change the base ID list. Degree day enrichment includes the complete HDD and CDD endpoint responses. Enrichment is generated before delivery. A transient enrichment failure is retried with the trigger instead of producing a partial payload.
| Response option | Subscriptions | Customer configuration |
|---|---|---|
| gridded | initialization_time.available , forecast_hour.available | No endpoint options. Returns forecast-hour and time-limited URL pairs. |
| interpolated_point_forecast | initialization_time.available , forecast_hour.available | Coordinates are required; variable, level, and distribution output are optional. Returns the complete endpoint response. |
| tropical_cyclones | tropical_cyclones.available | Format and basin are optional. Adds time-limited detail URLs for the base tropical cyclone IDs. |
| degree_days | degree_days.available | No endpoint options. Returns both complete degree day endpoint responses. |
Webhook Authentication
Webhook callback authentication is separate from the API request authentication used to manage webhooks.
WindBorne generates a signing secret and returns it only when the webhook is created. Store it securely. Every delivery includes Trigger-Id , Webhook-Timestamp , and Webhook-Signature headers. Read the unmodified request body as bytes, reject stale timestamps, and verify the HMAC before processing the payload.
The timestamp check limits replay attempts to five minutes. If duplicate processing within that window matters, also retain recently processed Trigger-Id values and reject repeats.
Delivery Identifiers
| Field | Scope | Description |
|---|---|---|
| webhook_id | Webhook | Persistent identifier for the webhook configuration. |
| subscription_id | Subscription | Persistent identifier for the subscription configuration. |
| trigger_id | Trigger | Identifier for one subscription firing. It is also sent in the Trigger-Id header and remains the same across retries. |
Webhook deliveries do not include a separate delivery-attempt identifier or delivery_id field. Each retry is another attempt for the same trigger and reuses its trigger_id .
Delivery & Retries
Return a 2xx response to acknowledge a delivery. Failed deliveries are retried.