NAV Navbar
shell python javascript csharp go

Introduction

Version: v1

The Tidetech Storm V1 API is a RESTful web service providing access to the latest data on tropical rotating storm activity for all ocean basins worldwide.

Forecasts are available out to 5 days/120 hours, or until the storm is expected to dissipate if less than 120 hours.

A list of currently active storms is provided via the /v1/active endpoint.

Metadata for each active storm can be accessed from /v1/storm/{id} and is updated 4 times/day for the Northern hemisphere, and 2 times/day for the Southern hemisphere. See the Metadata section for more details.

The GeoJSON representation of each storm contains: * Past storm tracks (lines) * Forecast storm tracks (lines) * Past storm positions and categories (points) * Forecast storm positions including storm categories, movement speed and direction at each forecast interval (0, 12, 24, 36, 48, 72, 96, 120 hours) * Forecast Error Boundaries for each forecast interval (lines) * Forecast Peak Gust Fields for the entire forecast (polygons)

Accessing the API

The API can be accessed at https://storm.tidetech.org/v1/

Accessing via browser

Explore the API by accessing the URLs provided in the response data. This is useful to get an understanding of the API structure, view metadata and GeoJSON features of currently active storms.

You can view active storms, metadata and GeoJSON in your browser by navigating to the index at https://storm.tidetech.org/v1/ and following the links provided.

Accessing via curl

curl is a popular lightweight command line tool used to transfer data to or from servers. It is available for all major operating systems and can be used to test the shell API request examples.

/v1/

curl --location --request GET https://storm.tidetech.org/v1/ \
--user "my_api_key:my_api_secret"
const axios = require("axios")

const apikey = "my_api_key";
const apisecret = "my_api_secret"
const url = "https://storm.tidetech.org/v1/"

axios.get(url, {
  auth: {
    username: apikey,
    password: apisecret,
  }
}).then((response) => {
  console.log(response.data)
}).catch((error) => {
  console.log(error)
})
from requests import request

apikey = "my_api_key"
apisecret = "my_api_secret"
url = "https://storm.tidetech.org/v1/"

response = request("GET", url, auth=(apikey, apisecret))

print(response.json())
string apikey = "my_api_key";
string apisecret = "my_api_secret";
string url = "https://storm.tidetech.org/v1/";

var client = new RestClient(url);
client.Authenticator = new HttpBasicAuthenticator(apikey, apisecret);
client.Timeout = -1;

var request = new RestRequest(Method.GET);

var response = client.Execute(request);
Console.WriteLine(response.Content);
package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
)

const (
  apikey = "my_api_key"
  apisecret = "my_api_secret"
  url = "https://storm.tidetech.org/v1/"
)

func main() {

  method := "GET"

  client := &http.Client {}
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
  }
  req.SetBasicAuth(apikey, apisecret)
  res, _ := client.Do(req)
  defer res.Body.Close()
  body, _ := ioutil.ReadAll(res.Body)

  fmt.Println(string(body))
}

Make sure to replace my_api_key and my_api_secret with your API Key and Secret.

Summary: API index

Description: The index endpoint lists the available API endpoints.

Endpoint /v1/

Method GET

Responses

Code Description
200 JSON object containing API index

The above command returns json structured like this:

{
  "links": {
    "active": "https://storm.tidetech.org/v1/active"
  }
}

/v1/active

curl --location --request GET https://storm.tidetech.org/v1/active \
--user "my_api_key:my_api_secret"
const axios = require("axios")

const apikey = "my_api_key";
const apisecret = "my_api_secret"
const url = "https://storm.tidetech.org/v1/active"

axios.get(url, {
  auth: {
    username: apikey,
    password: apisecret,
  }
}).then((response) => {
  console.log(response.data)
}).catch((error) => {
  console.log(error)
})
from requests import request

apikey = "my_api_key"
apisecret = "my_api_secret"
url = "https://storm.tidetech.org/v1/active"

response = request("GET", url, auth=(apikey, apisecret))

print(response.json())
string apikey = "my_api_key";
string apisecret = "my_api_secret";
string url = "https://storm.tidetech.org/v1/active";

var client = new RestClient(url);
client.Authenticator = new HttpBasicAuthenticator(apikey, apisecret);
client.Timeout = -1;

var request = new RestRequest(Method.GET);

var response = client.Execute(request);
Console.WriteLine(response.Content);
package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
)

const (
  apikey = "my_api_key"
  apisecret = "my_api_secret"
  url = "https://storm.tidetech.org/v1/active"
)

func main() {

  method := "GET"

  client := &http.Client {}
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
  }
  req.SetBasicAuth(apikey, apisecret)
  res, _ := client.Do(req)
  defer res.Body.Close()
  body, _ := ioutil.ReadAll(res.Body)

  fmt.Println(string(body))
}

Make sure to replace my_api_key and my_api_secret with your API Key and Secret.

Summary: Active storms index

Description: The active storms endpoint lists all currently active storms in all basins.

Endpoint /v1/active

Method GET

Responses

Code Description
200 JSON object containing active storms array

The above command returns json structured like this: With active storms:

{
  "data": [
    {
      "id": "202002E",
      "name": "AMANDA",
      "details": "https://storm.tidetech.org/v1/storm/202002E"
    },
    ...other active storms
  ]
}

Without active storms: json { "data": [] }

/v1/storm/{id}

curl --location --request GET https://storm.tidetech.org/v1/storm/202002E \
--user "my_api_key:my_api_secret"
const axios = require("axios")

const apikey = "my_api_key";
const apisecret = "my_api_secret"
const url = "https://storm.tidetech.org/v1/storm/202002E"

axios.get(url, {
  auth: {
    username: apikey,
    password: apisecret,
  }
}).then((response) => {
  console.log(response.data)
}).catch((error) => {
  console.log(error)
})
from requests import request

apikey = "my_api_key"
apisecret = "my_api_secret"
url = "https://storm.tidetech.org/v1/storm/202002E"

response = request("GET", url, auth=(apikey, apisecret))

print(response.json())
string apikey = "my_api_key";
string apisecret = "my_api_secret";
string url = "https://storm.tidetech.org/v1/storm/202002E";

var client = new RestClient(url);
client.Authenticator = new HttpBasicAuthenticator(apikey, apisecret);
client.Timeout = -1;

var request = new RestRequest(Method.GET);

var response = client.Execute(request);
Console.WriteLine(response.Content);
package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
)

const (
  apikey = "my_api_key"
  apisecret = "my_api_secret"
  url = "https://storm.tidetech.org/v1/storm/202002E"
)

func main() {

  method := "GET"

  client := &http.Client {}
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
  }
  req.SetBasicAuth(apikey, apisecret)
  res, _ := client.Do(req)
  defer res.Body.Close()
  body, _ := ioutil.ReadAll(res.Body)

  fmt.Println(string(body))
}

Make sure to replace my_api_key and my_api_secret with your API Key and Secret.

Summary: Storm metadata

Description: The /v2/storm/{id} endpoint returns the most recent metadata for that storm.

Endpoint /v1/storm/{id}

Method GET

Responses

Code Description
200 JSON object containing storm metadata

The above command returns json structured like this:

{
  "data": {
    "id": "202002E",
    "advisory": "2020-05-31T15:00:00Z",
    "is_active": true,
    "name": "AMANDA",
    "basin": "NEP",
    "category": "ts",
    "forecast_hours": 72,
    "geojson": "https://storm.tidetech.org/v1/storm/202002E/features",
    "event_number": 2,
    "position": [
      -90.3,
      14.7
    ],
    "movement": {
      "KPH": 17,
      "MPH": 10,
      "KTS": 9,
      "bearing": 6
    },
    "max_observed_category": "ts",
    "max_forecast_category": "ts",
    "name_list": [
      "02E",
      "AMANDA"
    ],
    "advisory_list": [
      "2020-05-31T03:00:00Z",
      "2020-05-31T09:00:00Z",
      "2020-05-31T15:00:00Z"
    ]
  }
}

Parameters

Name Located in Description Required Type
id path storm id Yes string

/v1/storm/{id}/features

curl --location --request GET https://storm.tidetech.org/v1/storm/202002E/features \
--user "my_api_key:my_api_secret"
const axios = require("axios")

const apikey = "my_api_key";
const apisecret = "my_api_secret"
const url = "https://storm.tidetech.org/v1/storm/202002E/features"

axios.get(url, {
    auth: {
        username: apikey,
        password: apisecret,
    }
}).then((response) => {
    console.log(response.data)
}).catch((error) => {
    console.log(error)
})
from requests import request

apikey = "my_api_key"
apisecret = "my_api_secret"
url = "https://storm.tidetech.org/v1/storm/202002E/features"

response = request("GET", url, auth=(apikey, apisecret))

print(response.json())
string apikey = "my_api_key";
string apisecret = "my_api_secret";
string url = "https://storm.tidetech.org/v1/storm/202002E/features";

var client = new RestClient(url);
client.Authenticator = new HttpBasicAuthenticator(apikey, apisecret);
client.Timeout = -1;

var request = new RestRequest(Method.GET);

var response = client.Execute(request);
Console.WriteLine(response.Content);
package main

import (
  "fmt"
  "net/http"
  "io/ioutil"
)

const (
  apikey = "my_api_key"
  apisecret = "my_api_secret"
  url = "https://storm.tidetech.org/v1/storm/202002E/features"
)

func main() {

  method := "GET"

  client := &http.Client {}
  req, err := http.NewRequest(method, url, nil)

  if err != nil {
    fmt.Println(err)
  }
  req.SetBasicAuth(apikey, apisecret)
  res, _ := client.Do(req)
  defer res.Body.Close()
  body, _ := ioutil.ReadAll(res.Body)

  fmt.Println(string(body))
}

Make sure to replace my_api_key and my_api_secret with your API Key and Secret.

Summary: Storm GeoJSON representation

Description: The /v2/storm/{id}/features endpoint returns the most recent GeoJSON FeatureCollection for that storm.

Endpoint /v1/storm/{id}/features

Method GET

Responses

Code Description
200 JSON object containing storm metadata

The above command returns json structured like this:

{
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [
            -91.1,
            12.3
          ],
          [
            -90.6,
            13
          ]
        ]
      },
      "properties": {
        "featureType": "stormTrack-past",
        "id": "202002E",
        "name": "AMANDA",
        "basin": "NEP",
        "intensity": "td",
        "color": "#00ccff",
        "opacity": 221
      }
    },
    {
      "type": "Feature",
      "geometry": {
        "type": "LineString",
        "coordinates": [
          [
            -90.6,
            13
          ],
          [
            -90.4,
            13.8
          ]
        ]
      },
      "properties": {
        "featureType": "stormTrack-past",
        "id": "202002E",
        "name": "AMANDA",
        "basin": "NEP",
        "intensity": "td",
        "color": "#00ccff",
        "opacity": 221
      }
    }
  ],
  ...more storm features
}

Parameters

Name Located in Description Required Type
id path storm id Yes string

Metadata

key value
id The storm ID. This ID is unique across the API.
advisory The UTC datetime of the most recent advisory for this storm.
is_active Whether or not the storm is currently active.
name The storm name.
basin The ocean basin in which the storm is currently active.
category The tropical cyclone classification of the storm as at the time of advisory.
forecast_hours The number of hours in the forecast, based on the estimated duration of the storm, up to 120 hours.
geojson Link to the GeoJSON representation of the storm forecast.
event_number The seasonal event number of the storm within a basin.
position The coordinates of the storm at the time of advisory.
movement The movement speed and bearing at the time of advisory.
max_observed_category The maximum tropical storm classification reached by the storm.
max_forecast_category The maximum tropical storm classification forecasted for the storm.
name_list All names assigned to a storm. Eg. ["TWENTYTHREE", "WALLACE"].
advisory_list Record of advisory dates.

Basin and Sub-basin Codes

Basins

code description
ATL North Atlantic
NEP Northeast Pacific
NWP Northwest Pacific
SWP Southwest Pacific
SIO South Indian Ocean
NIO North Indian Ocean

Sub-basins

code description
N North Atlantic
W Northwest Pacific
A Arabian Sea
B Bay of Bengal
E Northeast Pacific
C Central Pacific
P Southwest Pacific
S South Indian

Storm Categories

strength category color speed kts speed mph speed kph
Tropical Depression TD
#00CCFF
<34 <39 <63
Tropical Storm TS
#00FF00
34-63 39-73 63-118
Hurricane Cat1
#FFFF00
64-82 74-95 119-153
Hurricane Cat2
#FFCC00
83-95 96-110 154-177
Intense Hurricane Cat3
#FF6600
96-112 111-129 178-208
Intense Hurricane Cat4
#FF0000
113-136 130-156 209-251
Intense Hurricane Cat5
#CC00CC
>136 >156 >251

Errors

The Tidetech API uses the following error codes:

Error Code Meaning
400 Bad Request -- Your request is invalid.
401 Unauthorized -- Your API key is wrong.
403 Forbidden -- The requested resource is hidden for administrators only.
404 Not Found -- The specified resource could not be found.
405 Method Not Allowed -- You tried to access a resource with an invalid method.
410 Gone -- The resource requested has been removed from our servers.
418 I'm a teapot.
429 Too Many Requests.
500 Internal Server Error -- We had a problem with our server. Try again later.
503 Service Unavailable -- We're temporarily offline for maintenance. Please try again later.