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
andmy_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
andmy_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
andmy_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
andmy_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
andmy_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
andmy_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
andmy_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
andmy_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
andmy_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. |