NAV Navbar
shell python javascript csharp go r

Introduction

Version: v2

The Tidetech V2 API is a RESTful web service providing access to our full suite of weather and metocean dataset metadata, point data (JSON containing GeoJSON features) or area data (GRIB or NetCDF files).

Accessing the API

The API can be accessed at https://api.tidetech.org/v2/

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 even download forecasts, but you will need to access it programmatically to extract point and area data.

You can view dataset metadata and download forecast files in your browser by navigating to the index at https://api.tidetech.org/v2/ 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.

Authentication

There are only limited sample datasets available without authentication. To access all datasets enabled in your subscription, you must supply valid authentication details with your request.

Authenticated access

API Key and Secret

You can generate as many API keys as you require, and use them across your applications as you desire via the Tidetech Portal. Individual API keys can be revoked without removing access for other applications using different API keys. You do not need to expose your password in every deployment of your application. Additionally, API keys are tied to an organisation instead of a user, so if a user is removed from an organisation, any applications they have set up will continue to function using the API key.

Email address and password

You can also use your email address and password to authenticate your application with the API, although we don't recommend this method because it requires exposing your password everywhere you would like to use the API. Changing your password requires changing it everywhere you have used it, and if your password is exposed once, you can not disable just that one location.

Using an API Key and Secret solves these issues.

HTTP Basic authentication

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

const apikey = "my_api_key";
const apisecret = "my_api_secret"
const url = "https://api.tidetech.org/v2/auth/"

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

apikey = "my_api_key"
apisecret = "my_api_secret"
url = "https://api.tidetech.org/v2/auth/"

with requests.get(url, auth=(apikey, apisecret)) as r:
  r.raise_for_status()
  print(r.json())
string apikey = "my_api_key";
string apisecret = "my_api_secret";
string url = "https://api.tidetech.org/v2/auth/";

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://api.tidetech.org/v2/auth/"
)

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))
}
library('httr')
library('jsonlite')

apikey <- "my_api_key"
apisecret <- "my_api_secret"
url <- "https://api.tidetech.org/v2/auth/"

req <- GET(url, authenticate(apikey, apisecret, type="basic"))
output <- prettify(content(req, "text"))

print(output)

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

The above command returns json structured like this:

{
  "authenticated_as": {
    "type": "api-key",
    "id": "my_api_key",
    "organisation": "Test organisation"
  }
}

Using HTTP Basic authentication is the simplest authentication method, and is widely supported. You can use an API Key and Secret, which attached to your organisation authenticate using your email address and password, or you can use an API key and secret attached to your organisation.

Anonymous access

curl --location --request GET https://api.tidetech.org/v2/auth/
import requests

url = "https://api.tidetech.org/v2/auth/"

with requests.get(url) as r:
  r.raise_for_status()
  print(r.json())
const axios = require("axios")

const url = "https://api.tidetech.org/v2/auth/"

axios.get(url)
  .then((response) => {
    console.log(response.data)
  }).catch((error) => {
    console.log(error)
  })
string url = "https://api.tidetech.org/v2/auth/";

var client = new RestClient(url);
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 url = "https://api.tidetech.org/v2/auth/"

func main() {

  method := "GET"

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

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

  fmt.Println(string(body))
}
library('httr')
library('jsonlite')

url <- "https://api.tidetech.org/v2/auth/"

req <- GET(url)
output <- prettify(content(req, as="text"))

print(output)

The above command returns json structured like this:

{
    "authenticated_as": null
}

If you access the API without any authentication details, you will only be able to access the public datasets.

Browser authentication

To view all of your datasets through the browser you must first authenticate your browser session. You can do this by navigating to https://api.tidetech.org/v2/?login=true, which will provide a login form.

/v2/

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

const apikey = "my_api_key";
const apisecret = "my_api_secret"
const url = "https://api.tidetech.org/v2/auth/"

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

apikey = "my_api_key"
apisecret = "my_api_secret"
url = "https://api.tidetech.org/v2/auth/"

with requests.get(url, auth=(apikey, apisecret)) as r:
  r.raise_for_status()
  print(r.json())
string apikey = "my_api_key";
string apisecret = "my_api_secret";
string url = "https://api.tidetech.org/v2/auth/";

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://api.tidetech.org/v2/auth/"
)

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))
}
library('httr')
library('jsonlite')

apikey <- "my_api_key"
apisecret <- "my_api_secret"
url <- "https://api.tidetech.org/v2/auth/"

req <- GET(url, authenticate(apikey, apisecret, type="basic"))
output <- prettify(content(req, "text"))

print(output)

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 /v2/

Method GET

Parameters

Name Located in Description Required Type
login query add ?login=true to login to the API using an html form No boolean

Responses

Code Description
200 JSON object containing API index

The above command returns json structured like this:

{
  "links": {
    "index": "https://api.tidetech.org/v2/",
    "auth": "https://api.tidetech.org/v2/auth/",
    "login": "https://api.tidetech.org/v2/?login=true",
    "datasets": "https://api.tidetech.org/v2/datasets/"
  }
}

/v2/auth/

Summary: Check authentication status

Description: Check that you have successfully authenticated using the /v2/auth/ endpoint. See the Authentication section for more details.

Endpoint /v2/auth/

Method GET

curl --location --request GET https://api.tidetech.org/v2/auth/ \
--user 'my_api_key:my_api_secret'
const axios = require("axios")

const apikey = "my_api_key";
const apisecret = "my_api_secret"
const url = "https://api.tidetech.org/v2/auth/"

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

apikey = "my_api_key"
apisecret = "my_api_secret"
url = "https://api.tidetech.org/v2/auth/"

with requests.get(url, auth=(apikey, apisecret)) as r:
  r.raise_for_status()
  print(r.json())
string apikey = "my_api_key";
string apisecret = "my_api_secret";
string url = "https://api.tidetech.org/v2/auth/";

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://api.tidetech.org/v2/auth/"
)

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))
}
library('httr')
library('jsonlite')

apikey <- "my_api_key"
apisecret <- "my_api_secret"
url <- "https://api.tidetech.org/v2/auth/"

req <- GET(url, authenticate(apikey, apisecret, type="basic"))
output <- prettify(content(req, "text"))

print(output)

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

Responses

Code Description
200 JSON object containing authenticated entity
401 Unauthorized

The above command returns json structured like this:

{
  "authenticated_as": {
    "type": "api-key",
    "id": "my_api_key",
    "organisation": "Test organisation"
  }
}

/v2/datasets/

Summary: List available dataset groups

Description: The /v2/datasets/ endpoint lists all the dataset groups available to you and their URLS.

Endpoint /v2/datasets/

Method GET

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

const apikey = "my_api_key";
const apisecret = "my_api_secret"
const url = "https://api.tidetech.org/v2/datasets/"

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

apikey = "my_api_key"
apisecret = "my_api_secret"
url = "https://api.tidetech.org/v2/datasets/"

with requests.get(url, auth=(apikey, apisecret)) as r:
  r.raise_for_status()
  print(r.json())
string apikey = "my_api_key";
string apisecret = "my_api_secret";
string url = "https://api.tidetech.org/v2/datasets/";

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://api.tidetech.org/v2/datasets/"
)

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))
}
library('httr')
library('jsonlite')

apikey <- "my_api_key"
apisecret <- "my_api_secret"
url <- "https://api.tidetech.org/v2/datasets/"

req <- GET(url, authenticate(apikey, apisecret, type="basic"))
output <- prettify(content(req, "text"))

print(output)

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

Responses

Code Description
200 JSON object containing list of group objects

The above command returns json structured like this (shortened for brevity):

{
    "data": [
        {
            "type": "group",
            "id": "currents",
            "name": "Currents",
            "description": "Currents",
            "datasets": 10,
            "links": {
                "datasets": "https://api.tidetech.org/v2/datasets/currents/"
            }
        },
        {
            "type": "group",
            "id": "meteorology",
            "name": "Meteorology",
            "description": "Meteorology",
            "datasets": 2,
            "links": {
                "datasets": "https://api.tidetech.org/v2/datasets/meteorology/"
            }
        },
        ...other dataset groups
    ]
}

/v2/datasets/{group}/

Summary: List available datasets within a group

Description: The /v2/datasets/{group}/ endpoint lists all the datasets with current data, with a small amount of metadata, and URLs for the endpoints that extract data.

Endpoint /v2/datasets/{group}/

Method GET

curl --location --request GET https://api.tidetech.org/v2/datasets/currents/ \
--user "my_api_key:my_api_secret"
const axios = require("axios")

const apikey = "my_api_key";
const apisecret = "my_api_secret"
const url = "https://api.tidetech.org/v2/datasets/currents/"

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

apikey = "my_api_key"
apisecret = "my_api_secret"
url = "https://api.tidetech.org/v2/datasets/currents/"

with requests.get(url, auth=(apikey, apisecret)) as r:
  r.raise_for_status()
  print(r.json())
string apikey = "my_api_key";
string apisecret = "my_api_secret";
string url = "https://api.tidetech.org/v2/datasets/currents/";

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://api.tidetech.org/v2/datasets/currents/"
)

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))
}
library('httr')
library('jsonlite')

apikey <- "my_api_key"
apisecret <- "my_api_secret"
url <- "https://api.tidetech.org/v2/datasets/currents/"

req <- GET(url, authenticate(apikey, apisecret, type="basic"))
output <- prettify(content(req, "text"))

print(output)

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

Parameters

Name Located in Description Required Type
group path dataset group id Yes string

Responses

Code Description
200 JSON object containing list of group datasets

The above command returns json structured like this (shortened for brevity):

{
    "data": [
        {
            "type": "dataset",
            "id": "baltic_sea_currents",
            "name": "Baltic Sea Currents",
            "group": "Currents",
            "description": "Baltic Sea ocean currents model",
            "resolution_x": 0.028,
            "resolution_y": -0.0167,
            "timestep_duration": "PT3600.0S",
            "links": {
                "self": "https://api.tidetech.org/v2/datasets/currents/baltic_sea_currents/",
                "points": "https://api.tidetech.org/v2/datasets/currents/baltic_sea_currents/points/",
                "area": "https://api.tidetech.org/v2/datasets/currents/baltic_sea_currents/area/",
                "forecast": "https://api.tidetech.org/v2/datasets/currents/baltic_sea_currents/forecast/"
            }
        },
        ...other datasets within the group
    ]
}

/v2/datasets/{group}/{dataset}/

Summary: Dataset metadata

Description: The /v2/datasets/{group}/{dataset}/ endpoint returns all the available metadata for that dataset.

Endpoint /v2/datasets/{group}/{dataset}/

Method GET

curl --location --request GET https://api.tidetech.org/v2/datasets/currents/baltic_sea_currents/ \
--user "my_api_key:my_api_secret"
const axios = require("axios")

const apikey = "my_api_key";
const apisecret = "my_api_secret"
const url = "https://api.tidetech.org/v2/datasets/currents/baltic_sea_currents/"

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

apikey = "my_api_key"
apisecret = "my_api_secret"
url = "https://api.tidetech.org/v2/datasets/currents/baltic_sea_currents/"

with requests.get(url, auth=(apikey, apisecret)) as r:
  r.raise_for_status()
  print(r.json())
string apikey = "my_api_key";
string apisecret = "my_api_secret";
string url = "https://api.tidetech.org/v2/datasets/currents/baltic_sea_currents/";

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://api.tidetech.org/v2/datasets/currents/baltic_sea_currents/"
)

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))
}
library('httr')
library('jsonlite')

apikey <- "my_api_key"
apisecret <- "my_api_secret"
url <- "https://api.tidetech.org/v2/datasets/currents/baltic_sea_currents/"

req <- GET(url, authenticate(apikey, apisecret, type="basic"))
output <- prettify(content(req, "text"))

print(output)

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

Parameters

Name Located in Description Required Type
group path dataset group id Yes string
dataset path dataset id Yes string

Responses

Code Description
200 JSON object containing dataset metadata

The above command returns json structured like this:

{
    "data": {
        "type": "dataset",
        "id": "baltic_sea_currents",
        "name": "Baltic Sea Currents",
        "group": "Currents",
        "description": "Baltic Sea ocean currents model",
        "resolution_x": 0.028,
        "resolution_y": -0.0167,
        "timestep_duration": "PT3600.0S",
        "links": {
            "self": "https://api.tidetech.org/v2/datasets/currents/baltic_sea_currents/",
            "points": "https://api.tidetech.org/v2/datasets/currents/baltic_sea_currents/points/",
            "area": "https://api.tidetech.org/v2/datasets/currents/baltic_sea_currents/area/",
            "forecast": "https://api.tidetech.org/v2/datasets/currents/baltic_sea_currents/forecast/"
        },
        "parameters": [
            {
                "id": "UOGRD",
                "long_name": null,
                "description": "u-component of current",
                "grib_code": 49,
                "var_code": 49,
                "units": "m/s",
                "unit_long": "Metres per second",
                "fill_value": -9999
            },
            {
                "id": "VOGRD",
                "long_name": null,
                "description": "v-component of current",
                "grib_code": 50,
                "var_code": 50,
                "units": "m/s",
                "unit_long": "Metres per second",
                "fill_value": -9999
            }
        ],
        "start_timestep": "2019-05-26T12:00:00+00:00",
        "end_timestep": "2020-05-30T23:00:00+00:00",
        "forecast_timestep": "2020-05-26T00:00:00+00:00",
        "dataset_bounds": {
            "lon_min": 9.023,
            "lon_max": 30.499,
            "lat_min": 52.9909,
            "lat_max": 65.9
        }
    }
}

/v2/datasets/{group}/{dataset}/points/

Summary: Point data from dataset

Description: The /v2/datasets/{group}/{dataset}/points/ endpoint extracts data from a dataset at one or more points, for one or more parameters. The endpoint only accepts POST requests. POST requests must be in JSON format, with the appropriate Content-Type: application/json headers set.

Endpoint /v2/datasets/{group}/{dataset}/points/

Method POST

curl --location --request POST https://api.tidetech.org/v2/datasets/waves/global_waves/points/ \
--user "my_api_key:my_api_secret" \
--header "Content-Type: application/json" \
--data-raw '{
    "points": [
        {
            "id": "multipoint",
            "point": {
                "coordinates": [
                    [-8.695, 50.079],
                    [-1.472, 50.1438]
                ],
                "type": "MultiPoint"
            },
            "timestep": "2020-05-27T06:00:00Z",
            "parameters": [
                "HTSGW",
                "DIRPW"
            ]
        }
    ]
}'
const axios = require("axios")
const apikey = "my_api_key"
const apisecret = "my_api_secret"
const url = "https://api.tidetech.org/v2/datasets/waves/global_waves/points/"
const payload = {
    "points": [
        {
            "id": "multipoint",
            "point": {
                "coordinates": [
                    [-8.695, 50.079],
                    [-1.472, 50.1438]
                ],
                "type": "MultiPoint"
            },
            "timestep": "2020-05-27T06:00:00Z",
            "parameters": [
                "HTSGW",
                "DIRPW"
            ]
        }
    ]
}

axios.post(url, payload, {
    auth: {
        username: apikey,
        password: apisecret,
    }
}).then((response) => {
    console.log(JSON.stringify(response.data))
}).catch((error) => {
    console.log(error);
})
import requests

apikey = "my_api_key"
apisecret = "my_api_secret"
url = "https://api.tidetech.org/v2/datasets/waves/global_waves/points/"
payload = {
    "points": [
        {
            "id": "multipoint",
            "point": {
                "coordinates": [
                    [-8.695, 50.079],
                    [-1.472, 50.1438]
                ],
                "type": "MultiPoint"
            },
            "timestep": "2020-05-27T06:00:00Z",
            "parameters": [
                "HTSGW",
                "DIRPW"
            ]
        }
    ]
}

with requests.post(url, json=payload, auth=(apikey, apisecret)) as r:
    r.raise_for_status()
    print(r.json())
string apikey = "my_api_key";
string apisecret = "my_api_secret";
string url = "https://api.tidetech.org/v2/datasets/waves/global_waves/points/";
var payload = "{" +
    "\"points\": [" +
        "{" +
            "\"id\": \"multipoint\"," +
            "\"point\": {" +
                "\"coordinates\": [" +
                    "[-8.695, 50.079]," +
                    "[-1.472,50.1438]" +
                "]," +
                "\"type\": \"MultiPoint\"" +
            "}," +
            "\"timestep\": \"2020-05-27T06:00:00Z\"," +
            "\"parameters\": [" +
                "\"HTSGW\"," +
                "\"DIRPW\"" +
            "]" +
        "}" +
    "]" +
"}";

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

var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddJsonBody(payload);

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

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

const (
    apikey = "my_api_key"
    apisecret = "my_api_secret"
    url = "https://api.tidetech.org/v2/datasets/waves/global_waves/points/"
)

func main() {

    method := "POST"

    payload := strings.NewReader(`
    {
        "points": [
            {
                "id": "multipoint",
                "point": {
                    "coordinates": [
                        [-8.695, 50.079],
                        [-1.472, 50.1438]
                    ],
                    "type": "MultiPoint"
                },
                "timestep": "2020-05-27T06:00:00Z",
                "parameters": [
                    "HTSGW",
                    "DIRPW"
                ]
            }
        ]
    }
    `)

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

    if err != nil {
        fmt.Println(err)
    }
    req.SetBasicAuth(apikey, apisecret)
    req.Header.Add("Content-Type", "application/json")
    res, err := client.Do(req)
    defer res.Body.Close()
    body, err := ioutil.ReadAll(res.Body)

    fmt.Println(string(body))
}
library('httr')
library('jsonlite')

apikey <- "my_api_key"
apisecret <- "my_api_secret"
url <- "https://api.tidetech.org/v2/datasets/waves/global_waves/points/"

payload <- '{
    "points": [
        {
            "id": "multipoint",
            "point": {
                "coordinates": [
                    [-8.695, 50.079],
                    [-1.472, 50.1438]
                ],
                "type": "MultiPoint"
            },
            "timestep": "2020-05-27T06:00:00Z",
            "parameters": [
                "HTSGW",
                "DIRPW"
            ]
        }
    ]
}'

req <- POST(
    url,
    authenticate(apikey, apisecret, type="basic"),
    encode="json",
    body=fromJSON(payload))

output <- prettify(content(req, "text"))

print(output)

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

Parameters

Name Located in Description Required Type
group path dataset group id Yes string
dataset path dataset id Yes string
point body coordinates to extract Yes Point or MultiPoint
timestep body timestep to extract data for Yes string
id body user assigned identifier No string
parameters body dataset parameters No array of strings

Responses

Code Description
200 JSON object containing a GeoJSON FeatureCollection

The returned data is a GeoJSON FeatureCollection, with one Feature per Point or MultiPoint sent in. The data for each point will be returned in the properties field of the Feature.

The above command returns json containing GeoJSON point data:

{
    "data": {
        "type": "FeatureCollection",
        "features": [
            {
                "type": "Feature",
                "id": "multipoint",
                "geometry": {
                    "type": "MultiPoint",
                    "coordinates": [
                        [
                            -8.695,
                            50.079
                        ],
                        [
                            -1.472,
                            50.1438
                        ]
                    ]
                },
                "properties": {
                    "dataset": "global_waves",
                    "timestep": "2020-05-27T06:00:00+00:00",
                    "values": [
                        {
                            "HTSGW": 2.0299999713897705,
                            "DIRPW": 277.5
                        },
                        {
                            "HTSGW": 0.7599999904632568,
                            "DIRPW": 262.5
                        }
                    ]
                }
            }
        ]
    }
}

/v2/datasets/{group}/{dataset}/area/

Summary: Raster data from a dataset

Description: The /v2/datasets/{group}/{dataset}/area/ endpoint extracts data from a dataset over an entire area. The endpoint only accepts POST requests. POST requests must be in JSON format, with the appropriate Content-Type: application/json headers set.

Endpoint /v2/datasets/{group}/{dataset}/area/

Method POST

curl --location --request POST https://api.tidetech.org/v2/datasets/meteorology/global_meteorology/area/ \
--user "my_api_key:my_api_secret" \
--header "Content-Type: application/json" \
--data-raw '{
    "start_timestep": "2020-05-27T00:00:00Z",
    "end_timestep": "2020-05-27T12:00:00Z",
    "parameters": ["UGRD", "VGRD"],
    "polygon": {
        "type": "Polygon",
        "coordinates": [[
            [-1.2732, 50.8536],
            [-1.7080, 50.6650],
            [-1.2732, 50.5020],
            [-0.8165, 50.6691],
            [-1.2732, 50.8536]
        ]]
    }
}' \
--output global_met.nc
const fs = require("fs")
const axios = require("axios")

const apikey = "my_api_key"
const apisecret = "my_api_secret"
const url = "https://api.tidetech.org/v2/datasets/meteorology/global_meteorology/area/"
const payload = {
    "start_timestep": "2020-05-27T00:00:00Z",
    "end_timestep": "2020-05-27T12:00:00Z",
    "parameters": [
        "UGRD",
        "VGRD"
    ],
    "polygon": {
        "type": "Polygon",
        "coordinates": [
            [
                [-1.2732, 50.8536],
                [-1.708, 50.665],
                [-1.2732, 50.502],
                [-0.8165, 50.6691],
                [-1.2732, 50.8536]
            ]
        ]
    }
}

axios.post(url, payload, {
    responseType: "stream",
    auth: {
        username: apikey,
        password: apisecret,
    }
}).then((response) => {
    response.data.pipe(fs.createWriteStream("global_met.nc"))
}).catch((error) => {
    console.log(error)
})
import requests

apikey = "my_api_key"
apisecret = "my_api_secret"
url = "https://api.tidetech.org/v2/datasets/meteorology/global_meteorology/area/"
payload = {
    "start_timestep": "2020-05-27T00:00:00Z",
    "end_timestep": "2020-05-27T12:00:00Z",
    "parameters": [
        "UGRD",
        "VGRD"
    ],
    "polygon": {
        "type": "Polygon",
        "coordinates": [
            [
                [-1.2732,50.8536],
                [-1.708,50.665],
                [-1.2732,50.502],
                [-0.8165,50.6691],
                [-1.2732,50.8536]
            ]
        ]
    }
}

with requests.post(url, json=payload, auth=(apikey, apisecret), stream=True) as r:
    r.raise_for_status()
    with open("global_met.nc", "wb") as f:
        for chunk in r.iter_content(chunk_size=1024*1024):
            f.write(chunk)
string apikey = "my_api_key";
string apisecret = "my_api_secret";
string url = "https://api.tidetech.org/v2/datasets/meteorology/global_meteorology/area/";
string payload = "{" +
    "\"start_timestep\": \"2020-05-27T00:00:00Z\"," +
    "\"end_timestep\": \"2020-05-27T12:00:00Z\"," +
    "\"parameters\": [" +
        "\"UGRD\"," +
        "\"VGRD\"" +
    "]," +
    "\"polygon\": {" +
        "\"type\": \"Polygon\"," +
        "\"coordinates\": [" +
            "[" +
                "[-1.2732, 50.8536]," +
                "[-1.708, 50.665]," +
                "[-1.2732, 50.502]," +
                "[-0.8165, 50.6691]," +
                "[-1.2732, 50.8536]" +
            "]" +
        "]" +
    "}" +
"}";

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

var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
request.AddJsonBody(payload);

var response = client.DownloadData(request);
File.WriteAllBytes("global_met.nc", response);
package main

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

const (
    apikey = "my_api_key"
    apisecret = "my_api_secret"
    url = "https://api.tidetech.org/v2/datasets/meteorology/global_meteorology/area/"
)

func main() {

    method := "POST"

    payload := strings.NewReader(`
    {
        "start_timestep": "2020-05-27T00:00:00Z",
        "end_timestep": "2020-05-27T12:00:00Z",
        "parameters": ["UGRD", "VGRD"],
        "polygon": {
            "type": "Polygon",
            "coordinates": [[
                [-1.2732, 50.8536],
                [-1.7080, 50.6650],
                [-1.2732, 50.5020],
                [-0.8165, 50.6691],
                [-1.2732, 50.8536]
            ]]
        }
    }
    `)

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

    if err != nil {
        fmt.Println(err)
    }
    req.SetBasicAuth(apikey, apisecret)
    req.Header.Add("Content-Type", "application/json")
    res, _ := client.Do(req)
    defer res.Body.Close()
    data, _ := ioutil.ReadAll(res.Body)

    ioutil.WriteFile("global_met.nc", data, 0777)
}
library('httr')
library('jsonlite')

apikey <- "my_api_key"
apisecret <- "my_api_secret"
url <- "https://api.tidetech.org/v2/datasets/meteorology/global_meteorology/area/"
path <- "global_met.nc"

payload <- '{
    "start_timestep": "2020-05-27T00:00:00Z",
    "end_timestep": "2020-05-27T12:00:00Z",
    "parameters": ["UGRD", "VGRD"],
    "polygon": {
        "type": "Polygon",
        "coordinates": [[
            [-1.2732, 50.8536],
            [-1.7080, 50.6650],
            [-1.2732, 50.5020],
            [-0.8165, 50.6691],
            [-1.2732, 50.8536]
        ]]
    }
}'

req <- POST(
    url,
    authenticate(apikey, apisecret, type="basic"),
    encode="json",
    body=fromJSON(payload),
    write_disk(path, overwrite=TRUE),
    progress())

stop_for_status(req)

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

Parameters

Name Located in Description Required Type
group path dataset group id Yes string
dataset path dataset id Yes string
polygon body area to be extracted No Polygon or MultiPolygon
start_timestep body start timestep Yes string ISO8601
end_timestep body end timestep Yes string ISO8601
parameters body dataset parameters No array of strings
lon_resolution body resampled longitudinal resolution No float
lat_resolution body resampled latitudinal resolution No float
compress body "gz" or "bz2" compression No string
format body "nc" or "grb" file format No string

Responses

Code Description
200 Returns raster data in GRIB or NetCDF format

The above command returns area data in GRIB or NetCDF format

/v2/datasets/{group}/{dataset}/forecast/

Summary: download a dataset's most recent forecast

Description: The /v2/datasets/{group}/{dataset}/forecast/ endpoint will download the most recent forecast as a NetCDF or (if available) GRIB dataset.

The dataset contains all the parameters listed in /v2/datasets/{group}/{dataset}/, and all timesteps between forecast_timestep and end_timestep.

The API will return a 302 Redirect response to an Amazon S3 URL. This URL will only remain valid for a short period of time. You should make a new request to this endpoint, and get a new one-time S3 download URL, every time you need to download the forecast.

Endpoint /v2/datasets/{group}/{dataset}/forecast/

This endpoint does not allow you to select a spatial or temporal subset of the forecast, select a subset of the dataset bands, or resample the dataset resolution.

Method GET

curl --location --request GET https://api.tidetech.org/v2/datasets/currents/solent_currents/forecast/ \
--user "my_api_key:my_api_secret" \
--output solent_forecast.nc
const fs = require("fs")
const axios = require("axios")
const apikey = "my_api_key"
const apisecret = "my_api_secret"

axios.get("https://api.tidetech.org/v2/datasets/currents/solent_currents/forecast/", data, {
    responseType: "stream",
    auth: {
        username: apikey,
        password: apisecret,
    }
}).then((response) => {
    response.data.pipe(fs.createWriteStream("solent_forecast.nc"))
}).catch((error) => {
    console.log(error);
})
import requests

apikey = "my_api_key"
apisecret = "my_api_secret"
url = "https://api.tidetech.org/v2/datasets/currents/solent_currents/forecast/"

with requests.get(url, auth=(apikey, apisecret), stream=True) as r:
    r.raise_for_status()
    with open("solent_forecast.nc", "wb") as f:
        for chunk in r.iter_content(chunk_size=1024*1024):
            f.write(chunk)
var apikey = "my_api_key";
var apisecret = "my_api_secret";

var client = new RestClient("https://api.tidetech.org/v2/datasets/currents/solent_currents/forecast/");
client.Authenticator = new HttpBasicAuthenticator(apikey, apisecret);
client.Timeout = -1;

var request = new RestRequest(Method.GET);

var response = client.DownloadData(request);
File.WriteAllBytes("solent_forecast.nc", response);
package main

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

const (
    apikey = "my_api_key"
    apisecret = "my_api_secret"
)

func main() {

    url := "https://api.tidetech.org/v2/datasets/currents/solent_currents/forecast/"
    method := "GET"

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

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

    ioutil.WriteFile("solent_forecast.nc", data, 0777)
}
library('httr')

apikey <- "my_api_key"
apisecret <- "my_api_secret"
url <- "https://api.tidetech.org/v2/datasets/currents/solent_currents/forecast/"
path <- "solent_forecast.nc"

req <- GET(
    url,
    authenticate(apikey, apisecret, type="basic"),
    config(http_content_decoding=0, followlocation=0),
    write_disk(path, overwrite=TRUE))
if (status_code(req) == 302) {
    req2 <- GET(
        req$headers$location,
        add_headers(prefer = "respond-async"),
        config(http_content_decoding=0, followlocation=0),
        write_disk(path, overwrite=TRUE),
        progress())

    stop_for_status(req2)
} else {
    stop_for_status(req)
}

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

Parameters

Name Located in Description Required Type
group path dataset group id Yes string
dataset path dataset id Yes string
compress query file compression type No string
format query file format No string

Responses

Code Description
200 Returns raster data in GRIB or NetCDF format

The above command returns area data in GRIB or NetCDF format

Metadata

key value
id The dataset ID. This ID is unique across the API.
name A human-friendly name for this dataset.
description A long form text description of this dataset and its contents.
group The dataset group this dataset belongs to.
resolution_x The x resolution of the dataset in decimal degrees.
resolution_y The y resolution of the dataset in decimal degrees.
timestep_duration The time between dataset timesteps, expressed as an ISO8601 duration.
start_timestep The earliest timestep in this dataset. Earlier timesteps represent historical data.
end_timestep The latest timestep in this dataset. Later timesteps represent forecast data.
forecast_timestep Data for timesteps later than this datetime are forecasts, and the data may change as new models are run.
links Links to other endpoints relating to this dataset.
dataset_bounds The minimum and maximum latitude and longitude bounding box of this dataset.
parameters A list of parameters this dataset contains. Each parameter is an object with the following fields:
parameters.id The ID of this parameter. Use this to refer to a parameter when requesting a subset of parameters through the API.
parameters.long_name A human-friendly name for this parameter.
parameters.description A long form text description of this parameter.
parameters.unit_long The units (metres, metres per second, time, etc) for this parameter.
parameters.units Abbreviated form of the units for this parameter.
parameters.grib_code The World Meteorological Organisation (WMO) GRIB reference code.
parameters.var_code Deprecated. This is the same value as grib_code. It will be removed in a future release.
parameters.fill_value The value used to indicate no data in output netcdf files.

Parameters

Currents

grib_code description unit
DSLM Deviation of sea level from mean metres
UOGRD u-component of current metres per second
VOGRD v-component of current metres per second
WTMP Water temperature kelvin

Meteorology

grib_code description unit
GUST Surface wind gust metres per second
UGRD u-component of wind metres per second
VGRD v-component of wind metres per second
ICEC Ice concentration fraction
RH Relative humidity percent
PRMSL Pressure reduced to mean sea level pascal
TMP Air temperature kelvin
PRATE Precipitation rate kg per metreĀ² per second
TCDC Total cloud cover percent

Waves

grib_code description unit
HTSGW Significant height of combined wind waves and swell metres
PERPW Primary wave mean period seconds
DIRPW Primary wave direction degrees from true North
WVHGT Significant height of wind waves metres
WVPER Mean period of wind waves seconds
WVDIR Direction of wind waves (from) degrees from true North
SWELL Significant height of swell waves metres
SWPER Mean period of swell waves seconds
SWDIR Direction of swell waves (from) degrees from true North
LENPW Primary length metres

Oceanography

grib_code description unit
SALTY Salinity kg per kg
WTMP Water temperature kelvin
CHLA Mass concentration of total chlorophyll in sea water mg per mĀ³

Observations

grib_code description unit
BATHY Depth of sea floor metres
WTMP Water temperature kelvin

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.
422 Unprocessable Entity -- Please check your request body and/or parameters.
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.